Skip to content

Commit 15926dd

Browse files
r-nearkarim-en
andauthored
Add BorshSchema implementation for hash types and enable ABI generation (#945)
* Add BorshSchema implementation for hash types and enable ABI generation * Change to `reproducible-wasm` --------- Co-authored-by: karim-en <karim.alabtakh@nearone.org>
1 parent 2346133 commit 15926dd

File tree

11 files changed

+81
-28
lines changed

11 files changed

+81
-28
lines changed

contracts/near/Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contracts/near/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ overflow-checks = true
2020

2121
[workspace.dependencies]
2222
near-sdk = { version = "5.12", features = ["legacy", "unit-testing"] }
23-
borsh = "1"
23+
borsh = { version = "1.5.7", features = ["unstable__schema"] }
2424
rlp = "0.5.2"
2525
rlp-derive = "0.1.0"
2626
ethereum-types = "0.14.1"

contracts/near/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ MAKEFILE_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
33
MANIFEST := $(MAKEFILE_DIR)/Cargo.toml
44

55
build-eth2-client:
6-
cargo near build non-reproducible-wasm --manifest-path $(MAKEFILE_DIR)/eth2-client/Cargo.toml --out-dir $(MAKEFILE_DIR)/res --no-abi
6+
cargo near build reproducible-wasm --manifest-path $(MAKEFILE_DIR)/eth2-client/Cargo.toml --out-dir $(MAKEFILE_DIR)/res
77

88
build-prover:
99
cargo near build non-reproducible-wasm --manifest-path $(MAKEFILE_DIR)/eth-prover/Cargo.toml --out-dir $(MAKEFILE_DIR)/res --no-abi

contracts/near/eth-types/src/eth2.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,20 @@ pub type Epoch = u64;
1818
pub type ForkVersion = [u8; 4];
1919
pub type DomainType = [u8; 4];
2020

21-
#[derive(Debug, Clone)]
21+
#[derive(Debug, Clone, BorshSchema)]
2222
pub struct PublicKeyBytes(pub [u8; PUBLIC_KEY_BYTES_LEN]);
23-
#[derive(Debug, Clone)]
23+
#[derive(Debug, Clone, BorshSchema)]
2424
pub struct SignatureBytes(pub [u8; SIGNATURE_BYTES_LEN]);
25-
#[derive(Debug, Clone)]
25+
#[derive(Debug, Clone, BorshSchema)]
2626
pub struct SyncCommitteeBits(pub [u8; SYNC_COMMITTEE_BITS_SIZE_IN_BYTES]);
2727

2828
arr_wrapper_impl_tree_hash_and_borsh!(PublicKeyBytes, PUBLIC_KEY_BYTES_LEN);
2929
arr_wrapper_impl_tree_hash_and_borsh!(SignatureBytes, SIGNATURE_BYTES_LEN);
3030
arr_wrapper_impl_tree_hash_and_borsh!(SyncCommitteeBits, SYNC_COMMITTEE_BITS_SIZE_IN_BYTES);
3131

32-
#[derive(Debug, Clone, BorshDeserialize, BorshSerialize, tree_hash_derive::TreeHash)]
32+
#[derive(
33+
Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize, tree_hash_derive::TreeHash,
34+
)]
3335
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))]
3436
pub struct BeaconBlockHeader {
3537
#[cfg_attr(not(target_arch = "wasm32"), serde(with = "serde_utils::quoted_u64"))]
@@ -53,7 +55,7 @@ pub struct SigningData {
5355
pub domain: H256,
5456
}
5557

56-
#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)]
58+
#[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)]
5759
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))]
5860
pub struct ExtendedBeaconBlockHeader {
5961
pub header: BeaconBlockHeader,
@@ -72,48 +74,50 @@ impl From<HeaderUpdate> for ExtendedBeaconBlockHeader {
7274
}
7375
}
7476

75-
#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)]
77+
#[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)]
7678
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))]
7779
pub struct SyncCommitteePublicKeys(pub Vec<PublicKeyBytes>);
7880
vec_wrapper_impl_tree_hash!(SyncCommitteePublicKeys);
7981

80-
#[derive(Debug, Clone, BorshDeserialize, BorshSerialize, tree_hash_derive::TreeHash)]
82+
#[derive(
83+
Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize, tree_hash_derive::TreeHash,
84+
)]
8185
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))]
8286
pub struct SyncCommittee {
8387
pub pubkeys: SyncCommitteePublicKeys,
8488
pub aggregate_pubkey: PublicKeyBytes,
8589
}
8690

87-
#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)]
91+
#[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)]
8892
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))]
8993
pub struct SyncAggregate {
9094
pub sync_committee_bits: SyncCommitteeBits,
9195
pub sync_committee_signature: SignatureBytes,
9296
}
9397

94-
#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)]
98+
#[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)]
9599
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))]
96100
pub struct SyncCommitteeUpdate {
97101
pub next_sync_committee: SyncCommittee,
98102
pub next_sync_committee_branch: Vec<H256>,
99103
}
100104

101-
#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)]
105+
#[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)]
102106
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))]
103107
pub struct HeaderUpdate {
104108
pub beacon_header: BeaconBlockHeader,
105109
pub execution_block_hash: H256,
106110
pub execution_hash_branch: Vec<H256>,
107111
}
108112

109-
#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)]
113+
#[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)]
110114
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))]
111115
pub struct FinalizedHeaderUpdate {
112116
pub header_update: HeaderUpdate,
113117
pub finality_branch: Vec<H256>,
114118
}
115119

116-
#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)]
120+
#[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)]
117121
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))]
118122
pub struct LightClientUpdate {
119123
pub attested_beacon_header: BeaconBlockHeader,
@@ -124,7 +128,7 @@ pub struct LightClientUpdate {
124128
pub sync_committee_update: Option<SyncCommitteeUpdate>,
125129
}
126130

127-
#[derive(Clone, BorshDeserialize, BorshSerialize)]
131+
#[derive(Clone, BorshDeserialize, BorshSchema, BorshSerialize)]
128132
pub struct LightClientState {
129133
pub finalized_beacon_header: ExtendedBeaconBlockHeader,
130134
pub current_sync_committee: SyncCommittee,

contracts/near/eth-types/src/lib.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use borsh::io::Read;
2-
use borsh::{BorshDeserialize, BorshSerialize};
2+
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
33
use derive_more::{
44
Add, AddAssign, Display, Div, DivAssign, From, Into, Mul, MulAssign, Rem, RemAssign, Sub,
55
SubAssign,
@@ -78,6 +78,27 @@ macro_rules! uint_declare_wrapper_and_serde {
7878
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))]
7979
pub struct $name(pub ethereum_types::$name);
8080

81+
// For uint types (U64, U128, U256)
82+
impl borsh::BorshSchema for $name {
83+
fn declaration() -> String {
84+
stringify!($name).to_string()
85+
}
86+
87+
fn add_definitions_recursively(
88+
definitions: &mut std::collections::BTreeMap<String, borsh::schema::Definition>,
89+
) {
90+
// Define as a sequence of u64 values
91+
let definition = borsh::schema::Definition::Sequence {
92+
length_width: borsh::schema::Definition::ARRAY_LENGTH_WIDTH, // 0 for fixed-size
93+
length_range: $len as u64..=$len as u64, // Fixed length
94+
elements: u64::declaration(),
95+
};
96+
97+
borsh::schema::add_definition(Self::declaration(), definition, definitions);
98+
u64::add_definitions_recursively(definitions);
99+
}
100+
}
101+
81102
impl BorshSerialize for $name {
82103
#[inline]
83104
fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
@@ -124,7 +145,7 @@ pub type Signature = H520;
124145

125146
// Block Header
126147

127-
#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)]
148+
#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, BorshSchema)]
128149
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))]
129150
pub struct BlockHeader {
130151
pub parent_hash: H256,

contracts/near/eth-types/src/macros.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,27 @@ macro_rules! arr_ethereum_types_wrapper_impl_borsh_serde_ssz {
127127
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))]
128128
pub struct $name(pub ethereum_types::$name);
129129

130+
// For hash types (H64, H128, H160, etc.)
131+
impl borsh::BorshSchema for $name {
132+
fn declaration() -> String {
133+
stringify!($name).to_string()
134+
}
135+
136+
fn add_definitions_recursively(
137+
definitions: &mut std::collections::BTreeMap<String, borsh::schema::Definition>,
138+
) {
139+
// Define as a fixed-length byte array
140+
let definition = borsh::schema::Definition::Sequence {
141+
length_width: borsh::schema::Definition::ARRAY_LENGTH_WIDTH, // 0 for fixed-size arrays
142+
length_range: $len as u64..=$len as u64, // Fixed length
143+
elements: u8::declaration(),
144+
};
145+
146+
borsh::schema::add_definition(Self::declaration(), definition, definitions);
147+
u8::add_definitions_recursively(definitions);
148+
}
149+
}
150+
130151
impl From<&[u8; $len]> for $name {
131152
fn from(item: &[u8; $len]) -> Self {
132153
$name(item.into())

contracts/near/eth2-client/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ near-sdk.workspace = true
3535
borsh.workspace = true
3636
bitvec.workspace = true
3737
near-plugins.workspace = true
38+
near-abi = "0.4.3"
39+
schemars = "0.8.22"
3840

3941
[dev-dependencies]
4042
ethereum_serde_utils.workspace = true

contracts/near/eth2-utility/src/consensus.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::str::FromStr;
22

33
use bitvec::order::Lsb0;
44
use bitvec::prelude::BitVec;
5-
use borsh::{BorshDeserialize, BorshSerialize};
5+
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
66
use eth_types::eth2::*;
77
use eth_types::H256;
88
use tree_hash::TreeHash;
@@ -28,7 +28,7 @@ pub struct GeneralizedIndex {
2828
pub sync_committee_tree_index: u32,
2929
}
3030

31-
#[derive(PartialEq, BorshSerialize, BorshDeserialize)]
31+
#[derive(PartialEq, BorshSerialize, BorshDeserialize, BorshSchema)]
3232
pub enum Network {
3333
Mainnet,
3434
Goerli,

contracts/near/eth2-utility/src/types.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1-
use borsh::{BorshDeserialize, BorshSerialize};
1+
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
22
use eth_types::eth2::*;
33
use eth_types::H256;
4+
use near_sdk::near;
45
use near_sdk::AccountId;
56

67
/// Minimal information about a header.
7-
#[derive(Clone, BorshDeserialize, BorshSerialize)]
8+
#[derive(Clone)]
9+
#[near(serializers=[borsh])]
810
pub struct ExecutionHeaderInfo {
911
pub parent_hash: H256,
1012
pub block_number: u64,
1113
pub submitter: AccountId,
1214
}
1315

14-
#[derive(Clone, BorshDeserialize, BorshSerialize)]
16+
#[derive(Clone)]
17+
#[near(serializers=[borsh])]
1518
pub struct InitInput {
1619
pub network: String,
1720
pub finalized_execution_header: eth_types::BlockHeader,
@@ -24,7 +27,7 @@ pub struct InitInput {
2427
pub trusted_signer: Option<AccountId>,
2528
}
2629

27-
#[derive(Clone, BorshDeserialize, BorshSerialize, PartialEq)]
30+
#[derive(Clone, BorshDeserialize, BorshSerialize, PartialEq, BorshSchema)]
2831
pub enum ClientMode {
2932
SubmitLightClientUpdate,
3033
SubmitHeader,

eth2near/Cargo.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)