Skip to content

Commit c7d206c

Browse files
authored
Acceptance test plan (#233)
* test: add various tests Signed-off-by: Ivo Yankov <[email protected]> * test: update transactionReceipt assertions Signed-off-by: Ivo Yankov <[email protected]> * test: add negative tests for eth_getTransactionByBlockNumberAndIndex Signed-off-by: Ivo Yankov <[email protected]> * test: add negative tests for eth_getTransactionByBlockHashAndIndex Signed-off-by: Ivo Yankov <[email protected]> * wip: block assertions Signed-off-by: Ivo Yankov <[email protected]> * test: add tests for getBlockByHash and getBlockByNumber and update block assertions Signed-off-by: Ivo Yankov <[email protected]> * test: add negative tests for getBlockByHash and getBlockByNumber Signed-off-by: Ivo Yankov <[email protected]> * nit: resolve comments Signed-off-by: Ivo Yankov <[email protected]> * fix: update static values to reflect hip415 Signed-off-by: Ivo Yankov <[email protected]> * fix: update unit test assertions Signed-off-by: Ivo Yankov <[email protected]> * chore: empty commit to restart cicd Signed-off-by: Ivo Yankov <[email protected]>
1 parent 107c399 commit c7d206c

File tree

5 files changed

+258
-37
lines changed

5 files changed

+258
-37
lines changed

packages/relay/src/lib/eth.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -848,15 +848,15 @@ export class EthImpl implements Eth {
848848
hash: blockHash,
849849
logsBloom: EthImpl.emptyBloom, //TODO calculate full block boom in mirror node
850850
miner: EthImpl.zeroAddressHex,
851-
mixHash: EthImpl.emptyArrayHex,
852-
nonce: EthImpl.zeroHex8Byte,
851+
mixHash: EthImpl.emptyHex,
852+
nonce: EthImpl.zeroHex,
853853
number: EthImpl.numberTo0x(blockResponse.number),
854854
parentHash: blockResponse.previous_hash.substring(0, 66),
855-
receiptsRoot: EthImpl.emptyArrayHex,
855+
receiptsRoot: EthImpl.zeroHex,
856856
timestamp: EthImpl.numberTo0x(Number(timestamp)),
857857
sha3Uncles: EthImpl.emptyArrayHex,
858858
size: EthImpl.numberTo0x(blockResponse.size | 0),
859-
stateRoot: EthImpl.emptyArrayHex,
859+
stateRoot: EthImpl.zeroHex,
860860
totalDifficulty: EthImpl.zeroHex,
861861
transactions: transactionArray,
862862
transactionsRoot: transactionArray.length == 0 ? EthImpl.ethEmptyTrie : blockHash,

packages/relay/tests/lib/eth.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ const verifyBlockConstants = (block: Block) => {
5757
expect(block.difficulty).equal(EthImpl.zeroHex);
5858
expect(block.extraData).equal(EthImpl.emptyHex);
5959
expect(block.miner).equal(EthImpl.zeroAddressHex);
60-
expect(block.mixHash).equal(EthImpl.emptyArrayHex);
61-
expect(block.nonce).equal(EthImpl.zeroHex8Byte);
62-
expect(block.receiptsRoot).equal(EthImpl.emptyArrayHex);
60+
expect(block.mixHash).equal(EthImpl.emptyHex);
61+
expect(block.nonce).equal(EthImpl.zeroHex);
62+
expect(block.receiptsRoot).equal(EthImpl.zeroHex);
6363
expect(block.sha3Uncles).equal(EthImpl.emptyArrayHex);
64-
expect(block.stateRoot).equal(EthImpl.emptyArrayHex);
64+
expect(block.stateRoot).equal(EthImpl.zeroHex);
6565
expect(block.totalDifficulty).equal(EthImpl.zeroHex);
6666
expect(block.uncles).to.deep.equal([]);
6767
};

packages/server/tests/acceptance/rpc.spec.ts

Lines changed: 148 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ const ONE_TINYBAR = ethers.utils.parseUnits('1', 10);
7575
const ONE_WEIBAR = ethers.utils.parseUnits('1', 18);
7676

7777
const NON_EXISTING_ADDRESS = '0x5555555555555555555555555555555555555555';
78+
const NON_EXISTING_TX_HASH = '0x5555555555555555555555555555555555555555555555555555555555555555';
79+
const NON_EXISTING_BLOCK_HASH = '0x555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555';
80+
const NON_EXISTING_BLOCK_NUMBER = 99999999;
81+
const NON_EXISTING_INDEX = 999999;
7882

7983
describe('RPC Server Acceptance Tests', function() {
8084
this.timeout(240 * 1000); // 240 seconds
@@ -124,31 +128,106 @@ describe('RPC Server Acceptance Tests', function() {
124128
describe('Block related RPC calls', () => {
125129

126130
let mirrorBlock;
131+
let mirrorContractResults;
132+
let mirrorTransactions : any[] = [];
127133

128134
before(async () => {
129135
mirrorBlock = (await mirrorNode.get(`/blocks?block.number=${mirrorContractDetails.block_number}`)).blocks[0];
136+
const timestampQuery = `timestamp=gte:${mirrorBlock.timestamp.from}&timestamp=lte:${mirrorBlock.timestamp.to}`;
137+
mirrorContractResults = (await mirrorNode.get(`/contracts/results?${timestampQuery}`)).results;
138+
139+
for (let i = 0; i < mirrorContractResults.length; i++) {
140+
const res = mirrorContractResults[i];
141+
mirrorTransactions.push( (await mirrorNode.get(`/contracts/${res.contract_id}/results/${res.timestamp}`)) );
142+
}
143+
144+
});
145+
146+
it('should execute "eth_getBlockByHash", hydrated transactions not specified', async function() {
147+
const blockResult = await relay.call('eth_getBlockByHash', [mirrorBlock.hash]);
148+
Assertions.block(blockResult, mirrorBlock, mirrorTransactions, false);
149+
});
150+
151+
it('should execute "eth_getBlockByHash", hydrated transactions = false', async function() {
152+
const blockResult = await relay.call('eth_getBlockByHash', [mirrorBlock.hash, false]);
153+
Assertions.block(blockResult, mirrorBlock, mirrorTransactions, false);
154+
});
155+
156+
it('should execute "eth_getBlockByHash", hydrated transactions = true', async function() {
157+
const blockResult = await relay.call('eth_getBlockByHash', [mirrorBlock.hash, true]);
158+
Assertions.block(blockResult, mirrorBlock, mirrorTransactions, true);
130159
});
131160

132-
it('should execute "eth_getBlockByHash"', async function() {
133-
const relayBlock = await relay.call('eth_getBlockByHash', [mirrorBlock.hash, 'true']);
134-
Assertions.block(relayBlock, mirrorBlock);
161+
it('should execute "eth_getBlockByHash" for non-existing block hash and hydrated transactions = false', async function() {
162+
const blockResult = await relay.call('eth_getBlockByHash', [NON_EXISTING_BLOCK_HASH, false]);
163+
expect(blockResult).to.be.null;
135164
});
136165

137-
it('should execute "eth_getBlockByNumber"', async function() {
166+
it('should execute "eth_getBlockByHash" for non-existing block hash and hydrated transactions = true', async function() {
167+
const blockResult = await relay.call('eth_getBlockByHash', [NON_EXISTING_BLOCK_HASH, true]);
168+
expect(blockResult).to.be.null;
169+
});
170+
171+
it('should execute "eth_getBlockByNumber", hydrated transactions not specified', async function() {
172+
const blockResult = await relay.call('eth_getBlockByNumber', [mirrorBlock.number]);
173+
Assertions.block(blockResult, mirrorBlock, mirrorTransactions, false);
174+
});
175+
176+
it('should execute "eth_getBlockByNumber", hydrated transactions = false', async function() {
177+
const blockResult = await relay.call('eth_getBlockByNumber', [mirrorBlock.number, false]);
178+
Assertions.block(blockResult, mirrorBlock, mirrorTransactions, false);
179+
});
180+
181+
it('should execute "eth_getBlockByNumber", hydrated transactions = true', async function() {
138182
const blockResult = await relay.call('eth_getBlockByNumber', [mirrorBlock.number, true]);
139-
Assertions.block(blockResult, mirrorBlock);
183+
Assertions.block(blockResult, mirrorBlock, mirrorTransactions, true);
184+
});
185+
186+
it('should execute "eth_getBlockByNumber" for non existing block number and hydrated transactions = true', async function() {
187+
const blockResult = await relay.call('eth_getBlockByNumber', [NON_EXISTING_BLOCK_NUMBER, true]);
188+
expect(blockResult).to.be.null;
189+
});
190+
191+
it('should execute "eth_getBlockByNumber" for non existing block number and hydrated transactions = false', async function() {
192+
const blockResult = await relay.call('eth_getBlockByNumber', [NON_EXISTING_BLOCK_NUMBER, false]);
193+
expect(blockResult).to.be.null;
140194
});
141195

142196
it('should execute "eth_getBlockTransactionCountByHash"', async function() {
143197
const res = await relay.call('eth_getBlockTransactionCountByHash', [mirrorBlock.hash]);
144198
expect(res).to.be.equal(mirrorBlock.count);
145199
});
146200

201+
it('should execute "eth_getBlockTransactionCountByHash" for non-existing block hash', async function() {
202+
const res = await relay.call('eth_getBlockTransactionCountByHash', [NON_EXISTING_BLOCK_HASH]);
203+
expect(res).to.be.null;
204+
});
205+
147206
it('should execute "eth_getBlockTransactionCountByNumber"', async function() {
148207
const res = await relay.call('eth_getBlockTransactionCountByNumber', [mirrorBlock.number]);
149208
expect(res).to.be.equal(mirrorBlock.count);
150209
});
151210

211+
it('should execute "eth_getBlockTransactionCountByNumber" for non-existing block number', async function() {
212+
const res = await relay.call('eth_getBlockTransactionCountByNumber', [NON_EXISTING_BLOCK_NUMBER]);
213+
expect(res).to.be.null;
214+
});
215+
216+
it('should execute "eth_blockNumber"', async function() {
217+
218+
const mirrorBlocks = await mirrorNode.get(`blocks`);
219+
expect(mirrorBlocks).to.have.property('blocks');
220+
expect(mirrorBlocks.blocks.length).to.gt(0);
221+
const mirrorBlockNumber = mirrorBlocks.blocks[0].number;
222+
223+
const res = await relay.call('eth_blockNumber', []);
224+
const blockNumber = Number(res);
225+
expect(blockNumber).to.exist;
226+
227+
// In some rare occasions, the relay block might be equal to the mirror node block + 1
228+
// due to the mirror node block updating after it was retrieved and before the relay.call completes
229+
expect(blockNumber).to.be.oneOf([mirrorBlockNumber, mirrorBlockNumber + 1]);
230+
});
152231
});
153232

154233
describe('Transaction related RPC Calls', () => {
@@ -187,11 +266,33 @@ describe('RPC Server Acceptance Tests', function() {
187266
Assertions.transaction(response, mirrorContractDetails);
188267
});
189268

269+
it('should execute "eth_getTransactionByBlockHashAndIndex" for invalid block hash', async function() {
270+
const response = await relay.call('eth_getTransactionByBlockHashAndIndex',
271+
[NON_EXISTING_BLOCK_HASH, mirrorContractDetails.transaction_index]);
272+
expect(response).to.be.null;
273+
});
274+
275+
it('should execute "eth_getTransactionByBlockHashAndIndex" for invalid index', async function() {
276+
const response = await relay.call('eth_getTransactionByBlockHashAndIndex',
277+
[mirrorContractDetails.block_hash, NON_EXISTING_INDEX]);
278+
expect(response).to.be.null;
279+
});
280+
190281
it('should execute "eth_getTransactionByBlockNumberAndIndex"', async function() {
191282
const response = await relay.call('eth_getTransactionByBlockNumberAndIndex', [mirrorContractDetails.block_number, mirrorContractDetails.transaction_index]);
192283
Assertions.transaction(response, mirrorContractDetails);
193284
});
194285

286+
it('should execute "eth_getTransactionByBlockNumberAndIndex" for invalid index', async function() {
287+
const response = await relay.call('eth_getTransactionByBlockNumberAndIndex', [mirrorContractDetails.block_number, NON_EXISTING_INDEX]);
288+
expect(response).to.be.null;
289+
});
290+
291+
it('should execute "eth_getTransactionByBlockNumberAndIndex" for non-exising block number', async function() {
292+
const response = await relay.call('eth_getTransactionByBlockNumberAndIndex', [NON_EXISTING_BLOCK_NUMBER, mirrorContractDetails.transaction_index]);
293+
expect(response).to.be.null;
294+
});
295+
195296
it('should execute "eth_getTransactionReceipt" for hash of legacy transaction', async function() {
196297
const transaction = {
197298
...default155TransactionData,
@@ -202,11 +303,11 @@ describe('RPC Server Acceptance Tests', function() {
202303
const legacyTxHash = await relay.sendRawTransaction(signedTx);
203304
// Since the transactionId is not available in this context
204305
// Wait for the transaction to be processed and imported in the mirror node with axios-retry
205-
await mirrorNode.get(`contracts/results/${legacyTxHash}`);
306+
const mirrorResult = await mirrorNode.get(`contracts/results/${legacyTxHash}`);
206307

207308
const res = await relay.call('eth_getTransactionReceipt', [legacyTxHash]);
208309
// FIXME here we must assert that the alias address is the `from` / `to` and not the `0x` prefixed one
209-
Assertions.transactionReceipt(res, transaction, { from: Utils.idToEvmAddress(accounts[2].accountId.toString()) });
310+
Assertions.transactionReceipt(res, mirrorResult);
210311
});
211312

212313
it('should execute "eth_getTransactionReceipt" for hash of London transaction', async function() {
@@ -219,16 +320,15 @@ describe('RPC Server Acceptance Tests', function() {
219320
const transactionHash = await relay.sendRawTransaction(signedTx);
220321
// Since the transactionId is not available in this context
221322
// Wait for the transaction to be processed and imported in the mirror node with axios-retry
222-
await mirrorNode.get(`contracts/results/${transactionHash}`);
323+
const mirrorResult = await mirrorNode.get(`contracts/results/${transactionHash}`);
223324

224325
const res = await relay.call('eth_getTransactionReceipt', [transactionHash]);
225326
// FIXME here we must assert that the alias address is the `from` / `to` and not the `0x` prefixed one
226-
Assertions.transactionReceipt(res, transaction, { from: Utils.idToEvmAddress(accounts[2].accountId.toString()) });
327+
Assertions.transactionReceipt(res, mirrorResult);
227328
});
228329

229330
it('should execute "eth_getTransactionReceipt" for non-existing hash', async function() {
230-
const nonExistingTxHash = '0x5555555555555555555555555555555555555555555555555555555555555555';
231-
const res = await relay.call('eth_getTransactionReceipt', [nonExistingTxHash]);
331+
const res = await relay.call('eth_getTransactionReceipt', [NON_EXISTING_TX_HASH]);
232332
expect(res).to.be.null;
233333
});
234334

@@ -321,7 +421,7 @@ describe('RPC Server Acceptance Tests', function() {
321421
});
322422

323423
it('should execute "eth_getTransactionCount" for account with non-zero nonce', async function() {
324-
const account = await servicesNode.createAliasAccount(10);
424+
const account = await servicesNode.createAliasAccount();
325425
// Wait for account creation to propagate
326426
await mirrorNode.get(`/accounts/${account.accountId}`);
327427
const transaction = {
@@ -339,6 +439,25 @@ describe('RPC Server Acceptance Tests', function() {
339439
const res = await relay.call('eth_getTransactionCount', [account.address, 'latest']);
340440
expect(res).to.be.equal('0x1');
341441
});
442+
443+
it('should execute "eth_getTransactionByHash" for existing transaction', async function() {
444+
const transaction = {
445+
...defaultLondonTransactionData,
446+
to: mirrorContract.evm_address,
447+
nonce: await relay.getAccountNonce(accounts[2].address)
448+
};
449+
const signedTx = await accounts[2].wallet.signTransaction(transaction);
450+
const transactionHash = await relay.sendRawTransaction(signedTx);
451+
const mirrorTransaction = await mirrorNode.get(`/contracts/results/${transactionHash}`);
452+
453+
const res = await relay.call('eth_getTransactionByHash', [transactionHash]);
454+
Assertions.transaction(res, mirrorTransaction);
455+
});
456+
457+
it('should execute "eth_getTransactionByHash" for non-existing transaction and return null', async function() {
458+
const res = await relay.call('eth_getTransactionByHash', [NON_EXISTING_TX_HASH]);
459+
expect(res).to.be.null;
460+
});
342461
});
343462

344463
it('should execute "eth_estimateGas"', async function() {
@@ -381,6 +500,11 @@ describe('RPC Server Acceptance Tests', function() {
381500
});
382501

383502
describe('Hardcoded RPC Endpoints', () => {
503+
let mirrorBlock;
504+
505+
before(async () => {
506+
mirrorBlock = (await mirrorNode.get(`/blocks?block.number=${mirrorContractDetails.block_number}`)).blocks[0];
507+
});
384508

385509
it('should execute "eth_chainId"', async function() {
386510
const res = await relay.call('eth_chainId', [null]);
@@ -398,12 +522,22 @@ describe('RPC Server Acceptance Tests', function() {
398522
});
399523

400524
it('should execute "eth_getUncleByBlockHashAndIndex"', async function() {
401-
const res = await relay.call('eth_getUncleByBlockHashAndIndex', []);
525+
const res = await relay.call('eth_getUncleByBlockHashAndIndex', [mirrorBlock.hash, 0]);
526+
expect(res).to.be.null;
527+
});
528+
529+
it('should execute "eth_getUncleByBlockHashAndIndex" for non-existing block hash and index=0', async function() {
530+
const res = await relay.call('eth_getUncleByBlockHashAndIndex', [NON_EXISTING_BLOCK_HASH, 0]);
402531
expect(res).to.be.null;
403532
});
404533

405534
it('should execute "eth_getUncleByBlockNumberAndIndex"', async function() {
406-
const res = await relay.call('eth_getUncleByBlockNumberAndIndex', []);
535+
const res = await relay.call('eth_getUncleByBlockNumberAndIndex', [mirrorBlock.number, 0]);
536+
expect(res).to.be.null;
537+
});
538+
539+
it('should execute "eth_getUncleByBlockNumberAndIndex" for non-existing block number and index=0', async function() {
540+
const res = await relay.call('eth_getUncleByBlockNumberAndIndex', [NON_EXISTING_BLOCK_NUMBER, 0]);
407541
expect(res).to.be.null;
408542
});
409543

0 commit comments

Comments
 (0)