Skip to content

Commit

Permalink
Merge branch 'main' into implement-append-entries-to-log-storage
Browse files Browse the repository at this point in the history
  • Loading branch information
gabriel-aranha-cw authored Jun 27, 2024
2 parents f3e8927 + 159bbf3 commit 1c40ef5
Show file tree
Hide file tree
Showing 21 changed files with 189 additions and 218 deletions.
5 changes: 4 additions & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ fn print_build_directives() {
// Code generation: Proto files
// -----------------------------------------------------------------------------
fn generate_proto_structs() {
tonic_build::compile_protos("static/proto/append_entry.proto").unwrap();
tonic_build::configure()
.protoc_arg("--experimental_allow_proto3_optional")
.compile(&["static/proto/append_entry.proto"], &["static/proto"])
.unwrap();
}

// -----------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion chaos/experiments/leader-election.sh
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ check_leader() {
local grpc_address=$1

# Send the gRPC request using grpcurl and capture both stdout and stderr
response=$(grpcurl -import-path static/proto -proto append_entry.proto -plaintext -d '{"term": 0, "prevLogIndex": 0, "prevLogTerm": 0, "leader_id": "leader_id_value", "block_entry": {"number": 1, "hash": "hash_value", "transactions_root": "transactions_root_value", "gas_used": "gas_used_value", "gas_limit": "gas_limit_value", "bloom": "bloom_value", "timestamp": 123456789, "parent_hash": "parent_hash_value", "author": "author_value", "extra_data": "ZXh0cmFfZGF0YV92YWx1ZQ==", "miner": "miner_value", "difficulty": "difficulty_value", "receipts_root": "receipts_root_value", "uncle_hash": "uncle_hash_value", "size": 12345, "state_root": "state_root_value", "total_difficulty": "total_difficulty_value", "nonce": "nonce_value", "transaction_hashes": ["tx_hash1", "tx_hash2"]}}' "$grpc_address" append_entry.AppendEntryService/AppendBlockCommit 2>&1)
response=$(grpcurl -import-path static/proto -proto append_entry.proto -plaintext -d '{"term": 5, "prevLogIndex": 0, "prevLogTerm": 4, "leader_id": "leader_id_value", "block_entry": {"number": 1, "hash": "ZXh0cmFfZGF0YV92YWx1ZQ==", "transactions_root": "ZXh0cmFfZGF0YV92YWx1ZQ==", "gas_used": 999, "gas_limit": 999, "bloom": "ZXh0cmFfZGF0YV92YWx1ZQ==", "timestamp": 123456789, "parent_hash": "ZXh0cmFfZGF0YV92YWx1ZQ==", "author": "ZXh0cmFfZGF0YV92YWx1ZQ==", "extra_data": "ZXh0cmFfZGF0YV92YWx1ZQ==", "miner": "ZXh0cmFfZGF0YV92YWx1ZQ==", "receipts_root": "ZXh0cmFfZGF0YV92YWx1ZQ==", "uncle_hash": "ZXh0cmFfZGF0YV92YWx1ZQ==", "size": 12345, "state_root": "ZXh0cmFfZGF0YV92YWx1ZQ==", "transaction_hashes": []}}' "$grpc_address" append_entry.AppendEntryService/AppendBlockCommit 2>&1)

# Check the response for specific strings to determine the node status
if [[ "$response" == *"append_transaction_executions called on leader node"* ]]; then
Expand Down
78 changes: 52 additions & 26 deletions e2e/test/automine/e2e-json-rpc.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expect } from "chai";
import { keccak256 } from "ethers";
import { Block, Bytes, TransactionReceipt } from "web3-types";

import { ALICE, BOB } from "../helpers/account";
Expand All @@ -13,10 +14,12 @@ import {
TEST_BALANCE,
ZERO,
deployTestContractBalances,
prepareSignedTx,
send,
sendAndGetError,
sendEvmMine,
sendExpect,
sendRawTransaction,
sendReset,
subscribeAndGetEvent,
subscribeAndGetEventWithContract,
Expand All @@ -32,11 +35,6 @@ describe("JSON-RPC", () => {
(await sendExpect("hardhat_reset", [])).eq(true);
}
});

it("Code for non-existent contract is 0x", async () => {
const addressWithNothingDeployed = ALICE.address;
(await sendExpect("eth_getCode", [addressWithNothingDeployed, "latest"])).eq("0x");
});
});

describe("Metadata", () => {
Expand Down Expand Up @@ -80,11 +78,17 @@ describe("JSON-RPC", () => {
it("eth_getTransactionCount", async () => {
(await sendExpect("eth_getTransactionCount", [ALICE])).eq(ZERO);
(await sendExpect("eth_getTransactionCount", [ALICE, "latest"])).eq(ZERO);
(await sendExpect("eth_getTransactionCount", [ALICE, "pending"])).eq(ZERO);
});
it("eth_getBalance", async () => {
(await sendExpect("eth_getBalance", [ALICE])).eq(TEST_BALANCE);
(await sendExpect("eth_getBalance", [ALICE, "latest"])).eq(TEST_BALANCE);
});
it("eth_getCode", () => {
it("code for non-existent contract is 0x", async () => {
(await sendExpect("eth_getCode", [ALICE.address, "latest"])).eq("0x");
});
});
});

describe("Block", () => {
Expand All @@ -96,25 +100,25 @@ describe("JSON-RPC", () => {
});
let hash: Bytes;
describe("eth_getBlockByNumber", () => {
it("should fetch the genesis correctly", async () => {
it("fetches genesis block correctly", async () => {
let block: Block = await send("eth_getBlockByNumber", [ZERO, true]);
expect(block.hash).to.not.be.undefined;
hash = block.hash as Bytes; // get the genesis hash to use on the next test
expect(block.transactions.length).eq(0);
});
it("should return null if the block doesn't exist", async () => {
it("returns null if block does not exist", async () => {
const NON_EXISTANT_BLOCK = "0xfffffff";
let block = await send("eth_getBlockByNumber", [NON_EXISTANT_BLOCK, true]);
expect(block).to.be.null;
});
});
describe("eth_getBlockByHash", () => {
it("should fetch the genesis correctly", async () => {
it("fetches genesis block correctly", async () => {
let block: Block = await send("eth_getBlockByHash", [hash, true]);
expect(block.number).eq("0x0");
expect(block.transactions.length).eq(0);
});
it("should return null if the block doesn't exist", async () => {
it("returns null if block does not exist", async () => {
let block = await send("eth_getBlockByHash", [HASH_ZERO, true]);
expect(block).to.be.null;
});
Expand All @@ -128,7 +132,7 @@ describe("JSON-RPC", () => {

describe("Logs", () => {
describe("eth_getLogs", () => {
it("return no logs for queries after the last mined block", async () => {
it("returns no logs for queries after last mined block", async () => {
// mine a test transaction
const contract = await deployTestContractBalances();
const txResponse = await contract.connect(ALICE.signer()).add(ALICE.address, 10);
Expand All @@ -146,6 +150,31 @@ describe("JSON-RPC", () => {
});
});

describe("Transaction", () => {
describe("eth_sendRawTransaction", () => {
it("Returns an expected result when a contract transaction fails", async () => {
// deploy
const contract = await deployTestContractBalances();

// send a transaction that will fail
const signedTx = await prepareSignedTx({
contract,
account: ALICE,
methodName: "sub",
methodParameters: [ALICE.address, 1],
});
const expectedTxHash = keccak256(signedTx);
const actualTxHash = await sendRawTransaction(signedTx);

// validate
const txReceiptAfterMining = await ETHERJS.getTransactionReceipt(expectedTxHash);
expect(txReceiptAfterMining).exist;
expect(txReceiptAfterMining?.status).eq(0);
expect(actualTxHash).eq(expectedTxHash);
});
});
});

describe("Evm", () => {
async function latest(): Promise<{ timestamp: number; block_number: number }> {
const block = await send("eth_getBlockByNumber", ["latest", false]);
Expand All @@ -160,19 +189,19 @@ describe("JSON-RPC", () => {

describe("evm_setNextBlockTimestamp", () => {
let target = Math.floor(Date.now() / 1000) + 10;
it("Should set the next block timestamp", async () => {
it("sets the next block timestamp", async () => {
await send("evm_setNextBlockTimestamp", [target]);
await sendEvmMine();
expect((await latest()).timestamp).eq(target);
});

it("Should offset subsequent timestamps", async () => {
it("offsets subsequent timestamps", async () => {
await new Promise((resolve) => setTimeout(resolve, 1000));
await sendEvmMine();
expect((await latest()).timestamp).to.be.greaterThan(target);
});

it("Should reset the changes when sending 0", async () => {
it("resets the changes when sending 0", async () => {
await send("evm_setNextBlockTimestamp", [0]);
let mined_timestamp = Math.floor(Date.now() / 1000);
await sendEvmMine();
Expand All @@ -182,7 +211,7 @@ describe("JSON-RPC", () => {
.lte(Math.floor(Date.now() / 1000));
});

it("Should handle negative offsets", async () => {
it("handle negative offsets", async () => {
const past = Math.floor(Date.now() / 1000);
await new Promise((resolve) => setTimeout(resolve, 2000));
await send("evm_setNextBlockTimestamp", [past]);
Expand All @@ -200,40 +229,37 @@ describe("JSON-RPC", () => {
});

describe("Subscription", () => {
describe("HTTP", () => {
it("eth_subscribe fails with code 32603", async () => {
describe("eth_subscribe", () => {
it("fails on HTTP", async () => {
const error = await sendAndGetError("eth_subscribe", ["newHeads"]);
expect(error).to.not.be.null;
expect(error.code).eq(-32603); // Internal error
});
});

describe("WebSocket", () => {
it("Subscribe to newHeads receives success subscription event", async () => {
it("subscribes to newHeads receives success subscription event", async () => {
const waitTimeInMilliseconds = 40;
const response = await subscribeAndGetEvent("newHeads", waitTimeInMilliseconds);
expect(response).to.not.be.undefined;
expect(response.id).to.not.be.undefined;
expect(response.result).to.not.be.undefined;
});

it("Subscribe to logs receives success subscription event", async () => {
it("subscribes to logs receives success subscription event", async () => {
const waitTimeInMilliseconds = 40;
const response = await subscribeAndGetEvent("logs", waitTimeInMilliseconds);
expect(response).to.not.be.undefined;
expect(response.id).to.not.be.undefined;
expect(response.result).to.not.be.undefined;
});

it("Subscribe to newPendingTransactions receives success subscription event", async () => {
it("subscribes to newPendingTransactions receives success subscription event", async () => {
const waitTimeInMilliseconds = 40;
const response = await subscribeAndGetEvent("newPendingTransactions", waitTimeInMilliseconds);
expect(response).to.not.be.undefined;
expect(response.id).to.not.be.undefined;
expect(response.result).to.not.be.undefined;
});

it("Subscribe to unsupported receives error subscription event", async () => {
it("subscribes to unsupported receives error subscription event", async () => {
const waitTimeInMilliseconds = 40;
const response = await subscribeAndGetEvent("unsupportedSubscription", waitTimeInMilliseconds);
expect(response).to.not.be.undefined;
Expand All @@ -244,7 +270,7 @@ describe("JSON-RPC", () => {
expect(response.error.code).eq(-32602);
});

it("Validate newHeads event", async () => {
it("validates newHeads event", async () => {
const waitTimeInMilliseconds = 40;
const response = await subscribeAndGetEvent("newHeads", waitTimeInMilliseconds, 2);
expect(response).to.not.be.undefined;
Expand Down Expand Up @@ -276,7 +302,7 @@ describe("JSON-RPC", () => {
expect(result).to.have.property("baseFeePerGas").that.is.a("string");
});

it("Validate logs event", async () => {
it("validates logs event", async () => {
await sendReset();
const waitTimeInMilliseconds = 40;
const response = await subscribeAndGetEventWithContract("logs", waitTimeInMilliseconds, 2);
Expand All @@ -298,7 +324,7 @@ describe("JSON-RPC", () => {
expect(result).to.have.property("removed").that.is.a("boolean");
});

it("Validate newPendingTransactions event", async () => {
it("validates newPendingTransactions event", async () => {
await sendReset();
const waitTimeInMilliseconds = 40;
const response = await subscribeAndGetEventWithContract(
Expand Down
6 changes: 4 additions & 2 deletions e2e/test/automine/e2e-tx-parallel-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
TX_PARAMS,
deployTestContractBalances,
deployTestContractCounter,
pollForTransactions,
send,
sendGetNonce,
sendRawTransactions,
Expand Down Expand Up @@ -87,8 +88,9 @@ describe("Transaction: parallel TestContractBalances", async () => {
}

// send transactions in parallel
let hashes = await sendRawTransactions(signedTxs);
let failed = hashes.filter((x) => x === undefined).length;
const hashes = await sendRawTransactions(signedTxs);
const receipts = await pollForTransactions(hashes);
let failed = receipts.filter((r) => r.status == 0).length;

// check remaining balance
expect(await _contract.get(ALICE.address)).eq(15);
Expand Down
41 changes: 0 additions & 41 deletions e2e/test/issues/external/e2e-ebm-transaction-sending.ts

This file was deleted.

39 changes: 0 additions & 39 deletions e2e/test/issues/interval/e2e-ibm-pending-transactions.test.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/eth/block_miner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ impl BlockMiner {
self.storage.save_execution(tx_execution.clone())?;

// decide what to do based on mining mode
// FIXME consensus should be synchronous here and wait for the confirmation from the majority
let _ = self.notifier_pending_txs.send(tx_execution);
if self.mode.is_automine() {
self.mine_local_and_commit()?;
Expand Down
6 changes: 0 additions & 6 deletions src/eth/consensus/append_log_entries_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,11 @@ mod tests {
assert_eq!(block.hash, expected_block.hash);
assert_eq!(block.number, expected_block.number);
assert_eq!(block.parent_hash, expected_block.parent_hash);
assert_eq!(block.nonce, expected_block.nonce);
assert_eq!(block.uncle_hash, expected_block.uncle_hash);
assert_eq!(block.transactions_root, expected_block.transactions_root);
assert_eq!(block.state_root, expected_block.state_root);
assert_eq!(block.receipts_root, expected_block.receipts_root);
assert_eq!(block.miner, expected_block.miner);
assert_eq!(block.difficulty, expected_block.difficulty);
assert_eq!(block.total_difficulty, expected_block.total_difficulty);
assert_eq!(block.extra_data, expected_block.extra_data);
assert_eq!(block.size, expected_block.size);
assert_eq!(block.gas_limit, expected_block.gas_limit);
Expand Down Expand Up @@ -216,7 +213,6 @@ mod tests {
assert_eq!(execution.output, expected_execution.output);
assert_eq!(execution.from, expected_execution.from);
assert_eq!(execution.to, expected_execution.to);
assert_eq!(execution.block_hash, expected_execution.block_hash);
assert_eq!(execution.block_number, expected_execution.block_number);
assert_eq!(execution.transaction_index, expected_execution.transaction_index);
assert_eq!(execution.logs.len(), expected_execution.logs.len());
Expand All @@ -225,8 +221,6 @@ mod tests {
assert_eq!(log.topics, expected_log.topics);
assert_eq!(log.data, expected_log.data);
assert_eq!(log.log_index, expected_log.log_index);
assert_eq!(log.removed, expected_log.removed);
assert_eq!(log.transaction_log_index, expected_log.transaction_log_index);
}
assert_eq!(execution.gas, expected_execution.gas);
assert_eq!(execution.receipt_cumulative_gas_used, expected_execution.receipt_cumulative_gas_used);
Expand Down
1 change: 1 addition & 0 deletions src/eth/consensus/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod discovery;
pub mod forward_to;
#[allow(dead_code)]
mod log_entry;
pub mod utils;

mod server;

Expand Down
Loading

0 comments on commit 1c40ef5

Please sign in to comment.