Skip to content

Commit

Permalink
Add safe and finalized block tags support (polkadot-evm#853)
Browse files Browse the repository at this point in the history
* Add `safe` and `finalized` block tags support

* prettier
  • Loading branch information
tgmichel authored Sep 20, 2022
1 parent d3beddc commit fe12fdd
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 4 deletions.
18 changes: 17 additions & 1 deletion client/rpc-core/src/types/block_number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ pub enum BlockNumber {
Earliest,
/// Pending block (being mined)
Pending,
/// The most recent crypto-economically secure block.
/// There is no difference between Ethereum's `safe` and `finalized`
/// in Substrate finality gadget.
Safe,
/// The most recent crypto-economically secure block.
Finalized,
}

impl Default for BlockNumber {
Expand Down Expand Up @@ -86,6 +92,8 @@ impl Serialize for BlockNumber {
BlockNumber::Latest => serializer.serialize_str("latest"),
BlockNumber::Earliest => serializer.serialize_str("earliest"),
BlockNumber::Pending => serializer.serialize_str("pending"),
BlockNumber::Safe => serializer.serialize_str("safe"),
BlockNumber::Finalized => serializer.serialize_str("finalized"),
}
}
}
Expand All @@ -98,7 +106,7 @@ impl<'a> Visitor<'a> for BlockNumberVisitor {
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(
formatter,
"a block number or 'latest', 'earliest' or 'pending'"
"a block number or 'latest', 'safe', 'finalized', 'earliest' or 'pending'"
)
}

Expand Down Expand Up @@ -163,6 +171,8 @@ impl<'a> Visitor<'a> for BlockNumberVisitor {
"latest" => Ok(BlockNumber::Latest),
"earliest" => Ok(BlockNumber::Earliest),
"pending" => Ok(BlockNumber::Pending),
"safe" => Ok(BlockNumber::Safe),
"finalized" => Ok(BlockNumber::Finalized),
_ if value.starts_with("0x") => u64::from_str_radix(&value[2..], 16)
.map(BlockNumber::Num)
.map_err(|e| Error::custom(format!("Invalid block number: {}", e))),
Expand Down Expand Up @@ -196,6 +206,8 @@ mod tests {
BlockNumber::Num(number) => Some(number),
BlockNumber::Earliest => Some(0),
BlockNumber::Latest => Some(1000),
BlockNumber::Safe => Some(999),
BlockNumber::Finalized => Some(999),
BlockNumber::Pending => Some(1001),
_ => None,
}
Expand All @@ -208,13 +220,17 @@ mod tests {
let bn_u64: BlockNumber = serde_json::from_str(r#"420"#).unwrap();
let bn_tag_earliest: BlockNumber = serde_json::from_str(r#""earliest""#).unwrap();
let bn_tag_latest: BlockNumber = serde_json::from_str(r#""latest""#).unwrap();
let bn_tag_safe: BlockNumber = serde_json::from_str(r#""safe""#).unwrap();
let bn_tag_finalized: BlockNumber = serde_json::from_str(r#""finalized""#).unwrap();
let bn_tag_pending: BlockNumber = serde_json::from_str(r#""pending""#).unwrap();

assert_eq!(match_block_number(bn_dec).unwrap(), 42);
assert_eq!(match_block_number(bn_hex).unwrap(), 69);
assert_eq!(match_block_number(bn_u64).unwrap(), 420);
assert_eq!(match_block_number(bn_tag_earliest).unwrap(), 0);
assert_eq!(match_block_number(bn_tag_latest).unwrap(), 1000);
assert_eq!(match_block_number(bn_tag_safe).unwrap(), 999);
assert_eq!(match_block_number(bn_tag_finalized).unwrap(), 999);
assert_eq!(match_block_number(bn_tag_pending).unwrap(), 1001);
}
}
2 changes: 2 additions & 0 deletions client/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ pub mod frontier_backend_client {
BlockNumber::Latest => Some(BlockId::Hash(client.info().best_hash)),
BlockNumber::Earliest => Some(BlockId::Number(Zero::zero())),
BlockNumber::Pending => None,
BlockNumber::Safe => Some(BlockId::Hash(client.info().finalized_hash)),
BlockNumber::Finalized => Some(BlockId::Hash(client.info().finalized_hash)),
})
}

Expand Down
2 changes: 1 addition & 1 deletion ts-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"truffle": "^5.1.62",
"ts-node": "^8.10.2",
"typescript": "^3.9.6",
"web3": "^1.3.4"
"web3": "^1.8.0-rc.0"
},
"devDependencies": {
"@types/chai-as-promised": "^7.1.5",
Expand Down
30 changes: 30 additions & 0 deletions ts-tests/tests/test-block-tags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { expect } from "chai";
import { step } from "mocha-steps";

import { GENESIS_ACCOUNT, GENESIS_ACCOUNT_PRIVATE_KEY, GENESIS_ACCOUNT_BALANCE, EXISTENTIAL_DEPOSIT } from "./config";
import { createAndFinalizeBlock, describeWithFrontier, customRequest } from "./util";

describeWithFrontier("Frontier RPC (BlockNumber tags)", (context) => {
before("Send some transactions across blocks", async function () {
// block #1 finalized
await createAndFinalizeBlock(context.web3);
// block #2 not finalized
await createAndFinalizeBlock(context.web3, false);
});

step("`earliest` returns genesis", async function () {
expect((await context.web3.eth.getBlock("earliest")).number).to.equal(0);
});

step("`latest` returns `BlockchainInfo::best_hash` number", async function () {
expect((await context.web3.eth.getBlock("latest")).number).to.equal(2);
});

step("`finalized` uses `BlockchainInfo::finalized_hash` number", async function () {
expect((await context.web3.eth.getBlock("finalized")).number).to.equal(1);
});

step("`safe` is an alias for `finalized` in Polkadot", async function () {
expect((await context.web3.eth.getBlock("safe")).number).to.equal(1);
});
});
4 changes: 2 additions & 2 deletions ts-tests/tests/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ export async function customRequest(web3: Web3, method: string, params: any[]) {

// Create a block and finalize it.
// It will include all previously executed transactions since the last finalized block.
export async function createAndFinalizeBlock(web3: Web3) {
const response = await customRequest(web3, "engine_createBlock", [true, true, null]);
export async function createAndFinalizeBlock(web3: Web3, finalize: boolean = true) {
const response = await customRequest(web3, "engine_createBlock", [true, finalize, null]);
if (!response.result) {
throw new Error(`Unexpected result: ${JSON.stringify(response)}`);
}
Expand Down

0 comments on commit fe12fdd

Please sign in to comment.