Skip to content
This repository has been archived by the owner on Mar 24, 2023. It is now read-only.

feat: add blockSpecifer for blockParameter to support Eip1898 #476

Merged
merged 2 commits into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 38 additions & 18 deletions packages/api-server/src/methods/modules/eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1114,8 +1114,35 @@ export class Eth {
return undefined;
}

// handle block hash
// Note: don't check requireCanonical since Godwoken only has canonical blocks.
if (
typeof blockParameter === "object" &&
blockParameter.blockHash != null
) {
const block = await this.getBlockByHash([
blockParameter.blockHash,
false,
]);
if (block == null) {
throw new HeaderNotFoundError(
`Header not found by block hash ${blockParameter.blockHash}`
);
}
if (block.number == null) {
// means pending;
return undefined;
}
return BigInt(block.number);
}

// handle block number
const tipNumber: bigint = await this.getTipNumber();
const blockNumber: U64 = Uint64.fromHex(blockParameter).getValue();
const blockHexNum =
typeof blockParameter === "object" && blockParameter.blockNumber != null
? blockParameter.blockNumber
: (blockParameter as HexNumber);
const blockNumber: U64 = Uint64.fromHex(blockHexNum).getValue();
if (tipNumber < blockNumber) {
throw new HeaderNotFoundError();
}
Expand Down Expand Up @@ -1205,28 +1232,21 @@ export class Eth {
fromBlock: undefined | BlockParameter,
toBlock: undefined | BlockParameter
): Promise<[bigint, bigint]> {
let normalizedFromBlock;
let normalizedToBlock;
let normalizedFromBlock: bigint;
let normalizedToBlock: bigint;
const latestBlockNumber = await this.getTipNumber();

// See also:
// - https://github.com/nervosnetwork/godwoken-web3/pull/427#discussion_r918904239
// - https://github.com/nervosnetwork/godwoken-web3/pull/300/files/131542bd5cc272279d27760e258fb5fa5de6fc9a#r861541728
if (fromBlock === "latest" || fromBlock === "pending") {
normalizedFromBlock = latestBlockNumber;
} else if (fromBlock == null || fromBlock === "earliest") {
normalizedFromBlock = BigInt(0);
} else {
normalizedFromBlock = BigInt(fromBlock);
}
const _fromBlock: bigint | undefined = await this.parseBlockParameter(
fromBlock ?? "earliest"
);
normalizedFromBlock = _fromBlock ?? latestBlockNumber;

if (toBlock == null || toBlock === "latest" || toBlock === "pending") {
normalizedToBlock = latestBlockNumber;
} else if (toBlock === "earliest") {
normalizedToBlock = BigInt(0);
} else {
normalizedToBlock = BigInt(toBlock);
}
const _toBlock: bigint | undefined = await this.parseBlockParameter(
toBlock ?? "latest"
);
normalizedToBlock = _toBlock ?? latestBlockNumber;

return [normalizedFromBlock, normalizedToBlock];
}
Expand Down
13 changes: 11 additions & 2 deletions packages/api-server/src/methods/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HexNumber, HexString } from "@ckb-lumos/base";
import { Hash, HexNumber, HexString } from "@ckb-lumos/base";
export type Error = {
code?: number;
message: string;
Expand All @@ -16,7 +16,16 @@ export type Response = number | string | boolean | SyningStatus | Array<string>;

export type Callback = (err: Error, res?: any | Response) => void;

export type BlockParameter = HexNumber | "latest" | "earliest" | "pending";
export type BlockTag = "latest" | "earliest" | "pending";

// Eip1898 support block hash and block number
export interface BlockSpecifier {
keroro520 marked this conversation as resolved.
Show resolved Hide resolved
blockNumber?: HexNumber;
blockHash?: Hash;
requireCanonical?: boolean;
}

export type BlockParameter = HexNumber | BlockTag | BlockSpecifier;

export interface TransactionCallObject {
from?: HexString;
Expand Down
59 changes: 55 additions & 4 deletions packages/api-server/src/methods/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
validateHexNumber,
validateHexString,
} from "../util";
import { BlockParameter } from "./types";
import { BlockParameter, BlockSpecifier } from "./types";
import { logger } from "../base/logger";
import { InvalidParamsError, RpcError } from "./error";
import { CKB_SUDT_ID, RPC_MAX_GAS_LIMIT } from "./constant";
Expand Down Expand Up @@ -273,11 +273,62 @@ export function verifyBlockParameter(
return undefined;
}

const err = verifyHexNumber(blockParameter, index);
if (err) {
return err.padContext("blockParameter block number");
if (typeof blockParameter === "object") {
const err = verifyBlockSpecifier(blockParameter, index);
if (err) {
return err.padContext("blockSpecifier");
}
} else {
const err = verifyHexNumber(blockParameter, index);
if (err) {
return err.padContext("blockParameter block number");
}
}

return undefined;
}

export function verifyBlockSpecifier(
blockSpecifier: BlockSpecifier,
index: number
) {
if (typeof blockSpecifier !== "object") {
return invalidParamsError(index, `blockSpecifier must be an object`);
}

if (blockSpecifier.blockHash == null && blockSpecifier.blockNumber == null) {
return invalidParamsError(
index,
"blockSpecifier has no blockHash and blockNumber"
);
}

if (blockSpecifier.blockHash != null && blockSpecifier.blockNumber != null) {
return invalidParamsError(
index,
"blockHash and blockNumber can not exits at same time"
);
}

if (
blockSpecifier.requireCanonical != null &&
typeof blockSpecifier.requireCanonical !== "boolean"
) {
return invalidParamsError(index, "requireCanonical should be boolean type");
}
if (blockSpecifier.blockNumber != null) {
const err = verifyHexNumber(blockSpecifier.blockNumber, index);
if (err) {
return err.padContext("blockSpecifier block number");
}
}

if (blockSpecifier.blockHash != null) {
const err = verifyBlockHash(blockSpecifier.blockHash, index);
if (err) {
return err.padContext("blockSpecifier block hash");
}
}
return undefined;
}

Expand Down
20 changes: 0 additions & 20 deletions packages/api-server/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
TX_GAS,
TX_GAS_CONTRACT_CREATION,
} from "./methods/constant";
import { BlockParameter } from "./methods/types";

const { platform } = require("os");
const { version: packageVersion } = require("../../../package.json");
Expand All @@ -18,25 +17,6 @@ export function getClientVersion() {
)}`;
}

export function handleBlockParamter(block_paramter: BlockParameter): BigInt {
if (!block_paramter) throw new Error("block_parameter is undefind!");

switch (block_paramter) {
case "latest":
return BigInt("1" + "0".repeat(10)); // a very large number

case "earliest":
return BigInt(0);

case "pending":
// throw new Error("pending transaction unsupported.");
return BigInt("1" + "0".repeat(10)); // treat it as 'latest'

default:
return BigInt(block_paramter);
}
}

export function toCamel(s: string) {
return s.replace(/([-_][a-z])/gi, ($1) => {
return $1.toUpperCase().replace("-", "").replace("_", "");
Expand Down