Skip to content
This repository was archived by the owner on Feb 19, 2025. It is now read-only.

Commit 3b8e7b9

Browse files
author
dndll
committed
feat: use batched pollarding and cachable indexes
feat(wip): improve gas fees
1 parent a07e1fa commit 3b8e7b9

29 files changed

Lines changed: 2618 additions & 517 deletions
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/nix/store/6hhlmiyksac9s0328fg8giyfj4avz2s4-source
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/nix/store/714kd9iay1f89hspfp62f6xhch67n733-source
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/nix/store/g0ya1mggp8nnpkcz6yj3jvqyjqxsl2rw-source
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/nix/store/jvsbsgg960pkxgvd8wknhg7d490qni3q-source
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/nix/store/nbkbs33bkw54f60kv5c5y48714l00dpw-source
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/nix/store/sk4ga2wy0b02k7pnzakwq4r3jdknda4g-source
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/nix/store/mjg7w4vrlbkydkqki65srggpwpksz5pg-nix-shell-env

.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa.rc

Lines changed: 2060 additions & 0 deletions
Large diffs are not rendered by default.

.envrc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
if ! has nix_direnv_version || ! nix_direnv_version 2.2.0; then
2+
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.2.0/direnvrc" "sha256-5EwyKnkJNQeXrRkYbwwRBcXbibosCJqyIUuz9Xq+LRc="
3+
fi
4+
use flake

contracts/eth/nearprover/contracts/NearProver.sol

Lines changed: 88 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@ pragma solidity ^0.8;
33

44
import "rainbow-bridge-sol/nearbridge/contracts/AdminControlled.sol";
55
import "rainbow-bridge-sol/nearbridge/contracts/INearBridge.sol";
6-
import "rainbow-bridge-sol/nearbridge/contracts/NearDecoder.sol";
76
import "./ProofDecoder.sol";
87
import "./INearProver.sol";
98

9+
error InvalidOutcomeRoot();
10+
error InvalidBlockRoot();
11+
error InvalidOutcomeRootRoot();
12+
error InvalidBlockHash();
13+
1014
contract NearProver is INearProver, AdminControlled {
1115
using Borsh for Borsh.Data;
12-
using NearDecoder for Borsh.Data;
1316
using ProofDecoder for Borsh.Data;
1417

1518
INearBridge public bridge;
@@ -25,6 +28,27 @@ contract NearProver is INearProver, AdminControlled {
2528
uint constant UNPAUSE_ALL = 0;
2629
uint constant PAUSED_VERIFY = 1;
2730

31+
function lookupItems(ProofDecoder.LookupMerklePath memory proof, ProofDecoder.MerklePath memory cache)
32+
internal
33+
pure
34+
returns (ProofDecoder.MerklePath memory path)
35+
{
36+
for (uint256 i = 0; i < proof.items.length; i++) {
37+
if (proof.items.length == 0) {
38+
return path;
39+
}
40+
path.items = new ProofDecoder.MerklePathItem[](proof.items.length);
41+
ProofDecoder.LookupMerklePathItem memory lookup = proof.items[i];
42+
43+
if (lookup.either == 0) {
44+
path.items[i] = cache.items[lookup.index];
45+
} else if (lookup.either == 1) {
46+
path.items[i] = lookup.item;
47+
}
48+
}
49+
return path;
50+
}
51+
2852
function proveOutcome(bytes memory proofData, uint64 blockHeight)
2953
public
3054
view
@@ -33,30 +57,57 @@ contract NearProver is INearProver, AdminControlled {
3357
returns (bool)
3458
{
3559
Borsh.Data memory borsh = Borsh.from(proofData);
36-
ProofDecoder.FullOutcomeProof memory fullOutcomeProof = borsh.decodeFullOutcomeProof();
60+
ProofDecoder.Proof memory proof = borsh.decodeProof();
3761
borsh.done();
3862

39-
bytes32 hash = _computeRoot(
40-
fullOutcomeProof.outcome_proof.outcome_with_id.hash,
41-
fullOutcomeProof.outcome_proof.proof
42-
);
63+
bytes32 hash;
64+
ProofDecoder.BlindedProof memory blindedProof;
65+
ProofDecoder.MerklePath memory path;
66+
ProofDecoder.LookupMerklePathItem memory lookup;
67+
68+
for (uint256 index = 0; index < proof.batch.length; index++) {
69+
blindedProof = proof.batch[index];
70+
71+
// Outcome proof
72+
hash = _computeLookupRoot(blindedProof.outcome_hash, blindedProof.outcome_proof, proof.cache);
73+
74+
//Outcome root proof
75+
hash = _computeLookupRoot(sha256(abi.encodePacked(hash)), blindedProof.outcome_root_proof, proof.cache);
4376

44-
hash = sha256(abi.encodePacked(hash));
77+
if (hash != blindedProof.transaction_header.outcome_root) {
78+
revert InvalidOutcomeRoot();
79+
}
4580

46-
hash = _computeRoot(hash, fullOutcomeProof.outcome_root_proof);
81+
// Block hash from header
82+
hash = blindedProof.transaction_header.hash;
83+
if (hash != blindedProof.outcome_proof_block_hash) {
84+
revert InvalidBlockHash();
85+
}
4786

48-
require(
49-
hash == fullOutcomeProof.block_header_lite.inner_lite.outcome_root,
50-
"NearProver: outcome merkle proof is not valid"
51-
);
87+
// Block proof
88+
path.items = new ProofDecoder.MerklePathItem[](
89+
blindedProof.block_proof.items.length + proof.ancestry.items.length
90+
);
91+
for (uint256 i = 0; i < blindedProof.block_proof.items.length; i++) {
92+
lookup = blindedProof.block_proof.items[i];
93+
if (lookup.either == 0) {
94+
path.items[i] = proof.cache.items[lookup.index];
95+
} else if (lookup.either == 1) {
96+
path.items[i] = lookup.item;
97+
}
98+
}
99+
for (uint256 i = 0; i < proof.ancestry.items.length; i++) {
100+
path.items[blindedProof.block_proof.items.length + i] = proof.ancestry.items[i];
101+
}
52102

53-
bytes32 expectedBlockMerkleRoot = bridge.blockMerkleRoots(blockHeight);
103+
hash = _computeRoot(hash, path);
104+
if (hash != proof.client_block_merkle_root) {
105+
revert InvalidBlockRoot();
106+
}
54107

55-
require(
56-
_computeRoot(fullOutcomeProof.block_header_lite.hash, fullOutcomeProof.block_proof) ==
57-
expectedBlockMerkleRoot,
58-
"NearProver: block proof is not valid"
59-
);
108+
bytes32 expectedBlockMerkleRoot = bridge.blockMerkleRoots(blockHeight);
109+
require(hash == expectedBlockMerkleRoot, "NearProver: block merkle proof is not expected merkle root");
110+
}
60111

61112
return true;
62113
}
@@ -72,4 +123,22 @@ contract NearProver is INearProver, AdminControlled {
72123
}
73124
}
74125
}
126+
127+
function _computeLookupRoot(
128+
bytes32 node,
129+
ProofDecoder.LookupMerklePath memory proof,
130+
ProofDecoder.MerklePath memory cache
131+
) internal pure returns (bytes32 hash) {
132+
ProofDecoder.MerklePath memory path;
133+
path.items = new ProofDecoder.MerklePathItem[](proof.items.length);
134+
for (uint i = 0; i < proof.items.length; i++) {
135+
ProofDecoder.LookupMerklePathItem memory item = proof.items[i];
136+
if (item.either == 0) {
137+
path.items[i] = cache.items[item.index];
138+
} else if (item.either == 1) {
139+
path.items[i] = item.item;
140+
}
141+
}
142+
return _computeRoot(node, path);
143+
}
75144
}

0 commit comments

Comments
 (0)