From d7d3df9f321ff200b24bdfdb060ef6dc2696f7eb Mon Sep 17 00:00:00 2001 From: holgerd77 Date: Mon, 8 Jun 2020 18:18:56 +0200 Subject: [PATCH 1/2] Added eth_getBlockTransactionCountByHash RPC method --- lib/rpc/modules/eth.js | 23 +++ test/rpc/eth/getBlockByHash.js | 15 +- test/rpc/eth/getBlockByNumber.js | 15 +- .../rpc/eth/getBlockTransactionCountByHash.js | 142 ++++++++++++++++++ test/rpc/util.js | 15 ++ 5 files changed, 182 insertions(+), 28 deletions(-) create mode 100644 test/rpc/eth/getBlockTransactionCountByHash.js create mode 100644 test/rpc/util.js diff --git a/lib/rpc/modules/eth.js b/lib/rpc/modules/eth.js index b36e8ca..7601720 100644 --- a/lib/rpc/modules/eth.js +++ b/lib/rpc/modules/eth.js @@ -24,6 +24,9 @@ class Eth { this.getBlockByHash = middleware(this.getBlockByHash.bind(this), 2, [[validators.hex, validators.blockHash], [validators.bool]]) + this.getBlockTransactionCountByHash = middleware(this.getBlockTransactionCountByHash.bind(this), 1, + [[validators.hex, validators.blockHash]]) + this.protocolVersion = middleware(this.protocolVersion.bind(this), 0, []) } @@ -76,6 +79,26 @@ class Eth { } } + /** + * Returns the transaction count for a block given by the block hash + * @param {Array} [params] An array of one parameter: A block hash + * @param {Function} [cb] A function with an error object as the first argument and an actual value + * as the second argument + * @return {Promise} + */ + async getBlockTransactionCountByHash (params, cb) { + let [blockHash] = params + + try { + let block = await this._chain.getBlock(toBuffer(blockHash)) + + const json = block.toJSON(true) + cb(null, `0x${json.transactions.length.toString(16)}`) + } catch (err) { + cb(err) + } + } + /** * Returns the current ethereum protocol version * @param {Array<*>} [params] An empty array diff --git a/test/rpc/eth/getBlockByHash.js b/test/rpc/eth/getBlockByHash.js index d5ddc68..789a56e 100644 --- a/test/rpc/eth/getBlockByHash.js +++ b/test/rpc/eth/getBlockByHash.js @@ -3,20 +3,7 @@ const test = require('tape') const request = require('supertest') const { INVALID_PARAMS } = require('../../../lib/rpc/error-code') const { startRPC, closeRPC, createManager, createNode } = require('../helpers') - -function checkError (expectedCode, expectedMessage) { - return function (res) { - if (!res.body.error) { - throw new Error('should return an error object') - } - if (res.body.error.code !== expectedCode) { - throw new Error(`should have an error code ${expectedCode}`) - } - if (expectedMessage && res.body.error.message !== expectedMessage) { - throw new Error(`should have an error message "${expectedMessage}"`) - } - } -} +const { checkError } = require('../util') test('call eth_getBlockByHash with valid arguments', t => { const manager = createManager(createNode()) diff --git a/test/rpc/eth/getBlockByNumber.js b/test/rpc/eth/getBlockByNumber.js index 11141ab..ad0fac2 100644 --- a/test/rpc/eth/getBlockByNumber.js +++ b/test/rpc/eth/getBlockByNumber.js @@ -1,3 +1,4 @@ +import { checkError } from '../util' const test = require('tape') const request = require('supertest') @@ -18,20 +19,6 @@ function createBlockchain () { } } -function checkError (expectedCode, expectedMessage) { - return function (res) { - if (!res.body.error) { - throw new Error('should return an error object') - } - if (res.body.error.code !== expectedCode) { - throw new Error(`should have an error code ${expectedCode}`) - } - if (expectedMessage && res.body.error.message !== expectedMessage) { - throw new Error(`should have an error message "${expectedMessage}"`) - } - } -} - test('call eth_getBlockByNumber with valid arguments', t => { const manager = createManager(createNode({ blockchain: createBlockchain() })) const server = startRPC(manager.getMethods()) diff --git a/test/rpc/eth/getBlockTransactionCountByHash.js b/test/rpc/eth/getBlockTransactionCountByHash.js new file mode 100644 index 0000000..64eb7d8 --- /dev/null +++ b/test/rpc/eth/getBlockTransactionCountByHash.js @@ -0,0 +1,142 @@ +const test = require('tape') + +const request = require('supertest') +const { INVALID_PARAMS } = require('../../../lib/rpc/error-code') +const { startRPC, closeRPC, createManager, createNode } = require('../helpers') +const { checkError } = require('../util') + +test('call eth_getBlockTransactionCountByHash with valid arguments', t => { + const manager = createManager(createNode()) + const server = startRPC(manager.getMethods()) + + const req = { + jsonrpc: '2.0', + method: 'eth_getBlockTransactionCountByHash', + params: [ + '0x910abca1728c53e8d6df870dd7af5352e974357dc58205dea1676be17ba6becf' + ], + id: 1 + } + + request(server) + .post('/') + .set('Content-Type', 'application/json') + .send(req) + .expect(200) + .expect(res => { + if (res.body.result !== `0x1`) { + throw new Error('transaction count is not 1') + } + }) + .end((err, res) => { + closeRPC(server) + t.end(err) + }) +}) + +test('call eth_getBlockTransactionCountByHash with invalid block hash without 0x', t => { + const manager = createManager(createNode()) + const server = startRPC(manager.getMethods()) + + const req = { + jsonrpc: '2.0', + method: 'eth_getBlockTransactionCountByHash', + params: ['WRONG BLOCK NUMBER'], + id: 1 + } + const checkInvalidParams = checkError( + INVALID_PARAMS, + 'invalid argument 0: hex string without 0x prefix' + ) + + request(server) + .post('/') + .set('Content-Type', 'application/json') + .send(req) + .expect(200) + .expect(checkInvalidParams) + .end(err => { + closeRPC(server) + t.end(err) + }) +}) + +test('call eth_getBlockTransactionCountByHash with invalid hex string as block hash', t => { + const manager = createManager(createNode()) + const server = startRPC(manager.getMethods()) + + const req = { + jsonrpc: '2.0', + method: 'eth_getBlockTransactionCountByHash', + params: ['0xWRONG BLOCK NUMBER', true], + id: 1 + } + const checkInvalidParams = checkError( + INVALID_PARAMS, + 'invalid argument 0: invalid block hash' + ) + + request(server) + .post('/') + .set('Content-Type', 'application/json') + .send(req) + .expect(200) + .expect(checkInvalidParams) + .end(err => { + closeRPC(server) + t.end(err) + }) +}) + +test('call eth_getBlockTransactionCountByHash without first parameter', t => { + const manager = createManager(createNode()) + const server = startRPC(manager.getMethods()) + + const req = { + jsonrpc: '2.0', + method: 'eth_getBlockTransactionCountByHash', + params: [], + id: 1 + } + + const checkInvalidParams = checkError( + INVALID_PARAMS, + 'missing value for required argument 0' + ) + + request(server) + .post('/') + .set('Content-Type', 'application/json') + .send(req) + .expect(200) + .expect(checkInvalidParams) + .end(err => { + closeRPC(server) + t.end(err) + }) +}) + +test('call eth_getBlockTransactionCountByHash with invalid second parameter', t => { + const manager = createManager(createNode()) + const server = startRPC(manager.getMethods()) + + const req = { + jsonrpc: '2.0', + method: 'eth_getBlockTransactionCountByHash', + params: ['INVALID PARAMETER'], + id: 1 + } + + const checkInvalidParams = checkError(INVALID_PARAMS) + + request(server) + .post('/') + .set('Content-Type', 'application/json') + .send(req) + .expect(200) + .expect(checkInvalidParams) + .end(err => { + closeRPC(server) + t.end(err) + }) +}) diff --git a/test/rpc/util.js b/test/rpc/util.js new file mode 100644 index 0000000..ab96b1f --- /dev/null +++ b/test/rpc/util.js @@ -0,0 +1,15 @@ +module.exports = { + checkError (expectedCode, expectedMessage) { + return function (res) { + if (!res.body.error) { + throw new Error('should return an error object') + } + if (res.body.error.code !== expectedCode) { + throw new Error(`should have an error code ${expectedCode}`) + } + if (expectedMessage && res.body.error.message !== expectedMessage) { + throw new Error(`should have an error message "${expectedMessage}"`) + } + } + } +} From a555fc470380537ba6cc838c87e4835a90558c3c Mon Sep 17 00:00:00 2001 From: Ryan Ghods Date: Mon, 8 Jun 2020 11:41:00 -0700 Subject: [PATCH 2/2] Fix import to require Looks like ci is failing with `SyntaxError: Cannot use import statement outside a module`. I don't think this would happen when we are on typescript with a proper build pipeline, but for now changing to `require` might be easiest. --- test/rpc/eth/getBlockByNumber.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/rpc/eth/getBlockByNumber.js b/test/rpc/eth/getBlockByNumber.js index ad0fac2..b58b6e1 100644 --- a/test/rpc/eth/getBlockByNumber.js +++ b/test/rpc/eth/getBlockByNumber.js @@ -1,9 +1,8 @@ -import { checkError } from '../util' const test = require('tape') - const request = require('supertest') const { INVALID_PARAMS } = require('../../../lib/rpc/error-code') const { startRPC, closeRPC, createManager, createNode } = require('../helpers') +const { checkError } = require('../util') function createBlockchain () { const transactions = [