Skip to content

Commit

Permalink
calculate logs bloom
Browse files Browse the repository at this point in the history
  • Loading branch information
oXtxNt9U committed Feb 25, 2025
1 parent 376010a commit d0f2ebd
Show file tree
Hide file tree
Showing 24 changed files with 235 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,18 @@ export class EthGetTransactionReceipt implements Contracts.Api.RPC.Action {

Utils.assert.defined(transaction.data.blockHeight);

const header = await this.databaseService.getBlockHeader(transaction.data.blockHeight);
if (!header) {
// eslint-disable-next-line unicorn/no-null
return null;
}

const { receipt } = await this.evm.getReceipt(transaction.data.blockHeight, transaction.id);
if (!receipt) {
// eslint-disable-next-line unicorn/no-null
return null;
}

return this.app.resolve(ReceiptResource).transform(transaction.data, receipt);
return this.app.resolve(ReceiptResource).transform(transaction.data, header, receipt);
}
}
2 changes: 1 addition & 1 deletion packages/api-evm/source/resources/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class BlockResource {
parentHash: `0x${blockData.previousBlock}`,
nonce: "0x0000000000000000",
sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad4e2a311b82e5872087ed76f0f1ccf8f", // No uncles in ARK, this is hash of empty list
logsBloom: "", // TODO: Implement logs bloom,
logsBloom: `0x${blockData.logsBloom}`,
transactionsRoot: `0x${blockData.stateHash}`,
stateRoot: `0x${blockData.stateHash}`,
receiptsRoot: `0x${blockData.stateHash}`,
Expand Down
3 changes: 2 additions & 1 deletion packages/api-evm/source/resources/receipt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Contracts } from "@mainsail/contracts";
export class ReceiptResource {
public async transform(
transaction: Contracts.Crypto.TransactionData,
header: Contracts.Crypto.BlockHeader,
receipt: Contracts.Evm.TransactionReceipt,
): Promise<object> {
/* eslint-disable sort-keys-fix/sort-keys-fix */
Expand All @@ -21,7 +22,7 @@ export class ReceiptResource {
gasUsed: `0x${receipt.gasUsed.toString(16)}`,
contractAddress: receipt.deployedContractAddress,
logs: receipt.logs,
logsBloom: `0x${"0".repeat(128)}`, // TODO: Implement logs bloom
logsBloom: `0x${header.logsBloom}`,
type: "0x2",
status: receipt.success ? "0x1" : "0x0",
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ export class GenesisBlockGenerator extends Generator {
stateHash:
options.snapshot?.stateHash ??
"0000000000000000000000000000000000000000000000000000000000000000",
logsBloom: "0".repeat(512),
timestamp: dayjs(options.epoch).valueOf(),
totalAmount: options.snapshot ? Utils.BigNumber.make(options.premine) : totals.amount,
totalFee: totals.fee,
Expand Down
2 changes: 2 additions & 0 deletions packages/contracts/source/contracts/crypto/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export interface BlockData {
readonly round: number;
readonly previousBlock: string;
readonly stateHash: string;
readonly logsBloom: string;
readonly numberOfTransactions: number;
readonly totalGasUsed: number;
readonly totalAmount: BigNumber;
Expand All @@ -51,6 +52,7 @@ export interface BlockJson {
readonly round: number;
readonly previousBlock: string;
readonly stateHash: string;
readonly logsBloom: string;
readonly numberOfTransactions: number;
readonly totalGasUsed: number;
readonly totalAmount: string;
Expand Down
1 change: 1 addition & 0 deletions packages/contracts/source/contracts/evm/evm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export interface Instance extends CommitHandler {
getReceipt(height: number, txHash: string): Promise<GetReceiptResult>;
calculateActiveValidators(context: CalculateActiveValidatorsContext): Promise<void>;
updateRewardsAndVotes(context: UpdateRewardsAndVotesContext): Promise<void>;
logsBloom(commitKey: CommitKey): Promise<string>;
stateHash(commitKey: CommitKey, currentHash: string): Promise<string>;
codeAt(address: string): Promise<string>;
storageAt(address: string, slot: bigint): Promise<string>;
Expand Down
4 changes: 4 additions & 0 deletions packages/crypto-block/source/deserializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ export class Deserializer implements Contracts.Crypto.BlockDeserializer {
stateHash: {
type: "hash",
},
logsBloom: {
type: "hash",
size: 256,
},
numberOfTransactions: {
type: "uint16",
},
Expand Down
4 changes: 2 additions & 2 deletions packages/crypto-block/source/factory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe<{
assertBlockData(assert, block.data, blockData);
assertBlockData(assert, block.header, blockData);
assert.equal(block.transactions, []);
assert.string(block.serialized);
assert.equal(block.serialized, serialized);
});

it("#make - should make a block with transactions", async ({ factory }) => {
Expand All @@ -62,7 +62,7 @@ describe<{
assertBlockData(assert, block.data, blockDataWithTransactionsOriginal);
assertBlockData(assert, block.header, blockDataWithTransactionsOriginal);
assert.length(block.transactions, blockDataWithTransactionsOriginal.transactions.length);
assert.string(block.serialized);
assert.equal(block.serialized, serializedWithTransactions);

for (let index = 0; index < blockDataWithTransactionsOriginal.transactions.length; index++) {
assertTransactionData(
Expand Down
1 change: 1 addition & 0 deletions packages/crypto-block/source/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export class ServiceProvider extends Providers.ServiceProvider {
4 + // round
hashByteLength + // previousBlock
hashByteLength + // stateHash
256 + // logsBloom
2 + // numberOfTransactions
4 + // totalGasUsed
32 + // totalAmount
Expand Down
1 change: 1 addition & 0 deletions packages/crypto-block/source/schemas.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ describe<{
previousBlock: "0".repeat(64),
reward: 0,
stateHash: "0".repeat(64),
logsBloom: "0".repeat(512),
timestamp: 0,
totalAmount: 0,
totalFee: 0,
Expand Down
15 changes: 14 additions & 1 deletion packages/crypto-block/source/schemas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AnySchemaObject } from "ajv";

export const schemas: Record<"block" | "blockId" | "prefixedBlockId" | "blockHeader", AnySchemaObject> = {
export const schemas: Record<"block" | "blockId" | "prefixedBlockId" | "blockHeader" | "logsBloom", AnySchemaObject> = {
block: {
$id: "block",
$ref: "blockHeader",
Expand All @@ -26,6 +26,7 @@ export const schemas: Record<"block" | "blockId" | "prefixedBlockId" | "blockHea
previousBlock: { $ref: "blockId" },
reward: { bignumber: { minimum: 0 } },
stateHash: { $ref: "hex" },
logsBloom: { $ref: "logsBloom" },
timestamp: { maximum: 2 ** 48 - 1, minimum: 0, type: "integer" },
totalAmount: { bignumber: { minimum: 0 } },
totalFee: { bignumber: { minimum: 0 } },
Expand All @@ -38,6 +39,7 @@ export const schemas: Record<"block" | "blockId" | "prefixedBlockId" | "blockHea
"previousBlock",
"height",
"stateHash",
"logsBloom",
"totalGasUsed",
"totalAmount",
"totalFee",
Expand Down Expand Up @@ -68,4 +70,15 @@ export const schemas: Record<"block" | "blockId" | "prefixedBlockId" | "blockHea
],
type: "string",
},
logsBloom: {
$id: "logsBloom",
allOf: [
{
$ref: "hex",
maxLength: 512,
minLength: 512,
},
],
type: "string",
},
};
6 changes: 3 additions & 3 deletions packages/crypto-block/source/serializer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ describe<{
});

it("#size - should return size", ({ serializer }) => {
assert.equal(serializer.headerSize(), 237);
assert.equal(serializer.headerSize(), 493);

assert.equal(serializer.totalSize(blockData), 237);
assert.equal(serializer.totalSize(blockData), 493);
});

it("#size - should return size with transactions", async ({ serializer, sandbox }) => {
assert.equal(serializer.totalSize(blockDataWithTransactions), 463);
assert.equal(serializer.totalSize(blockDataWithTransactions), 719);
});

it("#serialize - should serialize and deserialize block", async ({ serializer, deserializer }) => {
Expand Down
6 changes: 6 additions & 0 deletions packages/crypto-block/source/serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ export class Serializer implements Contracts.Crypto.BlockSerializer {
stateHash: {
type: "hash",
},
logsBloom: {
type: "hash",
},
numberOfTransactions: {
type: "uint16",
},
Expand Down Expand Up @@ -89,6 +92,9 @@ export class Serializer implements Contracts.Crypto.BlockSerializer {
stateHash: {
type: "hash",
},
logsBloom: {
type: "hash",
},
numberOfTransactions: {
type: "uint16",
},
Expand Down
16 changes: 10 additions & 6 deletions packages/crypto-block/test/fixtures/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import { BigNumber } from "@mainsail/utils";
export const blockData: Contracts.Crypto.BlockData = {
generatorAddress: "0xB559F4FbB75c378CDd3Dd7CcbFeff9c5c2094E55",
height: 2,
id: "b60bd8c5c7c74dc5fdf971b1c5392e859aa6ca08e57f98e44e65faa7fd0e4684",
id: "6d9ec81edbe42628b7bb60c81bef94d53525580c99be8ca7efffd4a804ec7c24",
numberOfTransactions: 0,
payloadHash: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
payloadLength: 0,
previousBlock: "0000000000000000000000000000000000000000000000000000000000000000",
reward: BigNumber.ZERO,
round: 1,
stateHash: "0000000000000000000000000000000000000000000000000000000000000000",
logsBloom: "0".repeat(512),
timestamp: 1_703_128_709_748,
totalAmount: BigNumber.ZERO,
totalFee: BigNumber.ZERO,
Expand All @@ -23,14 +24,15 @@ export const blockData: Contracts.Crypto.BlockData = {
export const blockDataJson: Contracts.Crypto.BlockJson = {
generatorAddress: "0xB559F4FbB75c378CDd3Dd7CcbFeff9c5c2094E55",
height: 2,
id: "b60bd8c5c7c74dc5fdf971b1c5392e859aa6ca08e57f98e44e65faa7fd0e4684",
id: "6d9ec81edbe42628b7bb60c81bef94d53525580c99be8ca7efffd4a804ec7c24",
numberOfTransactions: 0,
payloadHash: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
payloadLength: 0,
previousBlock: "0000000000000000000000000000000000000000000000000000000000000000",
reward: "0",
round: 1,
stateHash: "0000000000000000000000000000000000000000000000000000000000000000",
logsBloom: "0".repeat(512),
timestamp: 1_703_128_709_748,
totalAmount: "0",
totalFee: "0",
Expand All @@ -40,19 +42,20 @@ export const blockDataJson: Contracts.Crypto.BlockJson = {
};

export const serialized =
"0174ba618a8c0102000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855b559f4fbb75c378cdd3dd7ccbfeff9c5c2094e55";
"0174ba618a8c010200000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855b559f4fbb75c378cdd3dd7ccbfeff9c5c2094e55";

export const blockDataWithTransactions: Contracts.Crypto.BlockData = {
generatorAddress: "0xB559F4FbB75c378CDd3Dd7CcbFeff9c5c2094E55",
height: 2,
id: "97160d3d9471d500a0f7cd0766a01bce7184a280c1dc566cdca9354b2a2f6b41",
id: "10ee5958aa6a97c60830a75f4c0f49ca02da76e5f13851567534a6837e0fa69d",
numberOfTransactions: 2,
payloadHash: "f01a3a2a2990990a64211feb47e2fa25c048decb3420ee52562fdc4931225c0f",
payloadLength: 226,
previousBlock: "0000000000000000000000000000000000000000000000000000000000000000",
reward: BigNumber.ZERO,
round: 1,
stateHash: "0000000000000000000000000000000000000000000000000000000000000000",
logsBloom: "0".repeat(512),
timestamp: 1_703_128_709_748,
totalAmount: BigNumber.ZERO,
totalFee: BigNumber.make("10000000000"),
Expand Down Expand Up @@ -101,14 +104,15 @@ export const blockDataWithTransactions: Contracts.Crypto.BlockData = {
export const blockDataWithTransactionsJson: Contracts.Crypto.BlockJson = {
generatorAddress: "0xB559F4FbB75c378CDd3Dd7CcbFeff9c5c2094E55",
height: 2,
id: "97160d3d9471d500a0f7cd0766a01bce7184a280c1dc566cdca9354b2a2f6b41",
id: "10ee5958aa6a97c60830a75f4c0f49ca02da76e5f13851567534a6837e0fa69d",
numberOfTransactions: 2,
payloadHash: "f01a3a2a2990990a64211feb47e2fa25c048decb3420ee52562fdc4931225c0f",
payloadLength: 226,
previousBlock: "0000000000000000000000000000000000000000000000000000000000000000",
reward: "0",
round: 1,
stateHash: "0000000000000000000000000000000000000000000000000000000000000000",
logsBloom: "0".repeat(512),
timestamp: 1_703_128_709_748,
totalAmount: "0",
totalFee: "10000000000",
Expand Down Expand Up @@ -153,4 +157,4 @@ export const blockDataWithTransactionsJson: Contracts.Crypto.BlockJson = {
version: 1,
};
export const serializedWithTransactions =
"0174ba618a8c010200000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200d0070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002540be4000000000000000000000000000000000000000000000000000000000000000000e2000000f01a3a2a2990990a64211feb47e2fa25c048decb3420ee52562fdc4931225c0fb559f4fbb75c378cdd3dd7ccbfeff9c5c2094e556d00000002f86a822710808085012a05f200830f424094be89811e15f611c1db12e59679b6f3dc1f4301558080c080a0921101a4583fb153ec00e501f3c2e2636114e1c8c58d2df8a19426cc066a6768a022db4bce1e0ace485ce0838d178b4d5bcfa9f69b315a14c580d9b01e5c980bdd6d00000002f86a822710018085012a05f200830f424094be89811e15f611c1db12e59679b6f3dc1f4301558080c080a06c9842bc78c2f68468cbf8a8f3fec0ae2679707ffb606a4b373dd01a02af55fca01a4c4d984d750678fb204ce8b7e97d860c974ac1a423f098dc4921acd2be0c7d";
"0174ba618a8c01020000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200d0070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002540be4000000000000000000000000000000000000000000000000000000000000000000e2000000f01a3a2a2990990a64211feb47e2fa25c048decb3420ee52562fdc4931225c0fb559f4fbb75c378cdd3dd7ccbfeff9c5c2094e556d00000002f86a822710808085012a05f200830f424094be89811e15f611c1db12e59679b6f3dc1f4301558080c080a0921101a4583fb153ec00e501f3c2e2636114e1c8c58d2df8a19426cc066a6768a022db4bce1e0ace485ce0838d178b4d5bcfa9f69b315a14c580d9b01e5c980bdd6d00000002f86a822710018085012a05f200830f424094be89811e15f611c1db12e59679b6f3dc1f4301558080c080a06c9842bc78c2f68468cbf8a8f3fec0ae2679707ffb606a4b373dd01a02af55fca01a4c4d984d750678fb204ce8b7e97d860c974ac1a423f098dc4921acd2be0c7d";
1 change: 1 addition & 0 deletions packages/crypto-block/test/helpers/prepare-sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const prepareSandbox = async (context) => {
4 + // round
hashByteLength + // previousBlock
hashByteLength + // stateHash
256 + // logsBloom
2 + // numberOfTransactions
4 + // totalGasUsed
32 + // totalAmount
Expand Down
5 changes: 5 additions & 0 deletions packages/evm-service/source/instances/evm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,11 @@ describe<{
assert.equal(hash, "d704de6546d2278905030a0c9f180a649964dbae8112f250a72a01629ec25f83");
});

it("should return logs bloom", async ({ instance }) => {
const logsBloom = await instance.logsBloom({ height: BigInt(0), round: BigInt(0) });
assert.equal(logsBloom, "0".repeat(512));
});

it("should return code", async ({ instance }) => {
const [sender] = wallets;

Expand Down
4 changes: 4 additions & 0 deletions packages/evm-service/source/instances/evm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ export class EvmInstance implements Contracts.Evm.Instance {
return this.#evm.stateHash(commitKey, currentHash);
}

public async logsBloom(commitKey: Contracts.Evm.CommitKey): Promise<string> {
return this.#evm.logsBloom(commitKey);
}

public mode(): Contracts.Evm.EvmMode {
return Contracts.Evm.EvmMode.Persistent;
}
Expand Down
53 changes: 53 additions & 0 deletions packages/evm/bindings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use mainsail_evm_core::{
db::{CommitKey, GenesisInfo, PendingCommit, PersistentDB},
legacy::{LegacyAddress, LegacyColdWallet},
logger::LogLevel,
logs_bloom,
receipt::{map_execution_result, TxReceipt},
state_changes::AccountUpdate,
state_commit, state_hash,
Expand Down Expand Up @@ -777,6 +778,36 @@ impl EvmInner {
}
}

pub fn logs_bloom(
&mut self,
commit_key: CommitKey,
) -> std::result::Result<String, EVMError<String>> {
if self
.pending_commit
.as_ref()
.is_some_and(|pending| pending.key != commit_key)
{
self.drop_pending_commit();
}

let pending_commit = self
.pending_commit
.get_or_insert_with(|| PendingCommit {
key: commit_key,
..Default::default()
})
.clone();

let result = logs_bloom::calculate(&pending_commit);

match result {
Ok(result) => Ok(result.encode_hex()),
Err(err) => Err(EVMError::Database(
format!("logs_bloom failed: {}", err).into(),
)),
}
}

pub fn dispose(&mut self) -> std::result::Result<(), EVMError<String>> {
// replace to drop any reference to logging hook
self.logger = JsLogger::new(None)
Expand Down Expand Up @@ -1186,6 +1217,15 @@ impl JsEvmWrapper {
)
}

#[napi(ts_return_type = "Promise<string>")]
pub fn logs_bloom(&mut self, node_env: Env, commit_key: JsCommitKey) -> Result<JsObject> {
let commit_key = CommitKey::try_from(commit_key)?;
node_env.execute_tokio_future(
Self::logs_bloom_async(self.evm.clone(), commit_key),
|&mut node_env, result| Ok(node_env.create_string_from_std(result)?),
)
}

#[napi(ts_return_type = "Promise<void>")]
pub fn dispose(&mut self, node_env: Env) -> Result<JsObject> {
node_env.execute_tokio_future(Self::dispose_async(self.evm.clone()), |_, _| Ok(()))
Expand Down Expand Up @@ -1388,6 +1428,19 @@ impl JsEvmWrapper {
}
}

async fn logs_bloom_async(
evm: Arc<tokio::sync::Mutex<EvmInner>>,
commit_key: CommitKey,
) -> Result<String> {
let mut lock = evm.lock().await;
let result = lock.logs_bloom(commit_key);

match result {
Ok(result) => Result::Ok(result),
Err(err) => Result::Err(serde::de::Error::custom(err)),
}
}

async fn get_accounts_async(
evm: Arc<tokio::sync::Mutex<EvmInner>>,
offset: u64,
Expand Down
1 change: 1 addition & 0 deletions packages/evm/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod db;
mod events;
pub mod legacy;
pub mod logger;
pub mod logs_bloom;
pub mod receipt;
pub mod state_changes;
pub mod state_commit;
Expand Down
Loading

0 comments on commit d0f2ebd

Please sign in to comment.