Skip to content

Commit

Permalink
Use binary search instead of backtracking to find common root (#580)
Browse files Browse the repository at this point in the history
* Use binary search instead of backtracking to find common root

* Add support for EIP-1559 (#600)

* Add support for EIP-1559

* Add interface to change bridge address

* Update yarn and gitignore

* Update eth2near relayer

* Remove console.log

* Restore getBlock function

* Update prover to support EIP 2718 txs (#602)

* Update prover to support EIP 2718 txs

* Use feature flag and implement 2718 compliance

* Compile near client contract

* Enable eip1559 by default and compile

* Allow deserialize London and PreLondon blocks

* Fix without eip1559 feature

* London HF fixes (#615)

* Add logs

* Add more logs

* dgb

* Don't deserialize on remove

* Update ehtereum.js dependency

* Prover: enable EIP1599 by default. Compile wasm.

Co-authored-by: Marcelo Fornet <[email protected]>

Co-authored-by: Kirill <[email protected]>

Co-authored-by: Kirill <[email protected]>

Co-authored-by: Kirill <[email protected]>
  • Loading branch information
mfornet and sept-en authored Aug 6, 2021
1 parent 3b34086 commit fe6ed9e
Show file tree
Hide file tree
Showing 24 changed files with 1,980 additions and 926 deletions.
4 changes: 2 additions & 2 deletions cli/commands/start/eth2near-relay.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const { nearAPI } = require('rainbow-bridge-utils')
const path = require('path')

class StartEth2NearRelayCommand {
static async execute ({
static async execute({
daemon,
nearNetworkId,
nearNodeUrl,
Expand Down Expand Up @@ -75,7 +75,7 @@ class StartEth2NearRelayCommand {
)
await clientContract.accessKeyInit()
console.log('Initializing eth2near-relay...', { ethNodeUrl, metricsPort })
relay.initialize(clientContract, { ethNodeUrl, totalSubmitBlock, gasPerTransaction, metricsPort })
relay.initialize(clientContract, { ethNodeUrl, totalSubmitBlock, gasPerTransaction, metricsPort, nearNetworkId })
console.log('Starting eth2near-relay...')
await relay.run()
}
Expand Down
5 changes: 3 additions & 2 deletions cli/init/near-contracts.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const {
} = require('rainbow-bridge-eth2near-block-relay')

class InitNearContracts {
static async execute ({
static async execute({
nearMasterAccount,
nearMasterSk,
nearClientAccount,
Expand Down Expand Up @@ -103,7 +103,8 @@ class InitNearContracts {
numConfirmations,
nearClientValidateEthash === 'true',
nearClientTrustedSigner || null,
robustWeb3
robustWeb3,
nearNetworkId
)
const proverContract = new EthOnNearProverContract(
new nearAPI.Account(near.connection, nearProverAccount),
Expand Down
3 changes: 2 additions & 1 deletion contracts/near/eth-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ serde_json = "1.0"
indicatif = "0.14"

[features]
default = []
default = ["eip1559"]
expensive_tests = []
eip1559 = ["eth-types/eip1559"]
9 changes: 8 additions & 1 deletion contracts/near/eth-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ impl EthClient {
#[serializer(borsh)] block_header: Vec<u8>,
#[serializer(borsh)] dag_nodes: Vec<DoubleNodeWithMerkleProof>,
) {
env::log("Add block header".as_bytes());
self.check_not_paused(PAUSE_ADD_BLOCK_HEADER);
let header: BlockHeader = rlp::decode(block_header.as_slice()).unwrap();

Expand Down Expand Up @@ -233,6 +234,7 @@ impl EthClient {
impl EthClient {
/// Record the header. If needed update the canonical chain and perform the GC.
fn record_header(&mut self, header: BlockHeader) {
env::log("Record header".as_bytes());
let best_info = self.infos.get(&self.best_header_hash).unwrap();
let header_hash = header.hash.unwrap();
let header_number = header.number;
Expand All @@ -258,6 +260,7 @@ impl EthClient {
all_hashes.push(header_hash);
self.all_header_hashes.insert(&header_number, &all_hashes);

env::log("Inserting header".as_bytes());
// Record full information about this header.
self.headers.insert(&header_hash, &header);
let info = HeaderInfo {
Expand All @@ -266,12 +269,14 @@ impl EthClient {
number: header_number,
};
self.infos.insert(&header_hash, &info);
env::log("Inserted".as_bytes());

// Check if canonical chain needs to be updated.
if info.total_difficulty > best_info.total_difficulty
|| (info.total_difficulty == best_info.total_difficulty
&& header.difficulty % 2 == U256::default())
{
env::log("Canonical chain needs to be updated.".as_bytes());
// If the new header has a lower number than the previous header, we need to clean it
// going forward.
if best_info.number > info.number {
Expand Down Expand Up @@ -330,10 +335,11 @@ impl EthClient {

/// Remove information about the headers that are at least as old as the given header number.
fn gc_headers(&mut self, mut header_number: u64) {
env::log(format!("Run headers GC. Used gas: {}", env::used_gas()).as_bytes());
loop {
if let Some(all_headers) = self.all_header_hashes.get(&header_number) {
for hash in all_headers {
self.headers.remove(&hash);
self.headers.remove_raw(&hash.try_to_vec().unwrap());
self.infos.remove(&hash);
}
self.all_header_hashes.remove(&header_number);
Expand All @@ -346,6 +352,7 @@ impl EthClient {
break;
}
}
env::log(format!("Finish headers GC. Used gas: {}", env::used_gas()).as_bytes());
}

/// Verify PoW of the header.
Expand Down
2 changes: 2 additions & 0 deletions contracts/near/eth-prover/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,6 @@ near-primitives = { git = "https://github.com/nearprotocol/nearcore.git" }
near-runtime-standalone = { git = "https://github.com/nearprotocol/nearcore.git" }

[features]
default = ["eip1559"]
expensive_tests = []
eip1559 = ["eth-types/eip1559"]
12 changes: 12 additions & 0 deletions contracts/near/eth-prover/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,18 @@ impl EthProver {
}
}
}

pub fn set_bridge(&mut self, bridge: AccountId) {
assert_self();
env::log(
format!(
"Old bridge account: {} New bridge account {}",
self.bridge_smart_contract, bridge
)
.as_bytes(),
);
self.bridge_smart_contract = bridge;
}
}

admin_controlled::impl_admin_controlled!(EthProver, paused);
Expand Down
3 changes: 3 additions & 0 deletions contracts/near/eth-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ rlp = "0.4.2"
rlp-derive = "0.1.0"
ethereum-types = "0.9.2"
derive_more = "^0.99.2"

[features]
eip1559 = []
160 changes: 155 additions & 5 deletions contracts/near/eth-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use derive_more::{
};
use ethereum_types;
use rlp::{
Decodable as RlpDecodable, DecoderError as RlpDecoderError, Encodable as RlpEncodable, Rlp,
RlpStream,
Decodable as RlpDecodable, DecoderError as RlpDecoderError, DecoderError,
Encodable as RlpEncodable, Rlp, RlpStream,
};
use rlp_derive::{RlpDecodable as RlpDecodableDerive, RlpEncodable as RlpEncodableDerive};
use rlp_derive::RlpDecodable as RlpDecodableDerive;
#[cfg(not(target_arch = "wasm32"))]
use serde::{Deserialize, Serialize};
use std::io::{Error, Write};
Expand Down Expand Up @@ -175,7 +175,7 @@ pub type Signature = H520;

// Block Header

#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)]
#[derive(Debug, Clone, BorshSerialize)]
#[cfg_attr(not(target_arch = "wasm32"), derive(Serialize, Deserialize))]
pub struct BlockHeader {
pub parent_hash: H256,
Expand All @@ -193,11 +193,120 @@ pub struct BlockHeader {
pub extra_data: Vec<u8>,
pub mix_hash: H256,
pub nonce: H64,
#[cfg(feature = "eip1559")]
pub base_fee_per_gas: u64,

pub hash: Option<H256>,
pub partial_hash: Option<H256>,
}

#[derive(BorshDeserialize)]
pub struct BlockHeaderLondon {
pub parent_hash: H256,
pub uncles_hash: H256,
pub author: Address,
pub state_root: H256,
pub transactions_root: H256,
pub receipts_root: H256,
pub log_bloom: Bloom,
pub difficulty: U256,
pub number: u64,
pub gas_limit: U256,
pub gas_used: U256,
pub timestamp: u64,
pub extra_data: Vec<u8>,
pub mix_hash: H256,
pub nonce: H64,
pub base_fee_per_gas: u64,

pub hash: Option<H256>,
pub partial_hash: Option<H256>,
}

impl From<BlockHeaderLondon> for BlockHeader {
fn from(header: BlockHeaderLondon) -> Self {
Self {
parent_hash: header.parent_hash,
uncles_hash: header.uncles_hash,
author: header.author,
state_root: header.state_root,
transactions_root: header.transactions_root,
receipts_root: header.receipts_root,
log_bloom: header.log_bloom,
difficulty: header.difficulty,
number: header.number,
gas_limit: header.gas_limit,
gas_used: header.gas_used,
timestamp: header.timestamp,
extra_data: header.extra_data,
mix_hash: header.mix_hash,
nonce: header.nonce,
#[cfg(feature = "eip1559")]
base_fee_per_gas: header.base_fee_per_gas,
hash: header.hash,
partial_hash: header.partial_hash,
}
}
}

#[derive(BorshDeserialize)]
pub struct BlockHeaderPreLondon {
pub parent_hash: H256,
pub uncles_hash: H256,
pub author: Address,
pub state_root: H256,
pub transactions_root: H256,
pub receipts_root: H256,
pub log_bloom: Bloom,
pub difficulty: U256,
pub number: u64,
pub gas_limit: U256,
pub gas_used: U256,
pub timestamp: u64,
pub extra_data: Vec<u8>,
pub mix_hash: H256,
pub nonce: H64,

pub hash: Option<H256>,
pub partial_hash: Option<H256>,
}

impl From<BlockHeaderPreLondon> for BlockHeader {
fn from(header: BlockHeaderPreLondon) -> Self {
Self {
parent_hash: header.parent_hash,
uncles_hash: header.uncles_hash,
author: header.author,
state_root: header.state_root,
transactions_root: header.transactions_root,
receipts_root: header.receipts_root,
log_bloom: header.log_bloom,
difficulty: header.difficulty,
number: header.number,
gas_limit: header.gas_limit,
gas_used: header.gas_used,
timestamp: header.timestamp,
extra_data: header.extra_data,
mix_hash: header.mix_hash,
nonce: header.nonce,
#[cfg(feature = "eip1559")]
base_fee_per_gas: 7,
hash: header.hash,
partial_hash: header.partial_hash,
}
}
}

impl BorshDeserialize for BlockHeader {
fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
if let Ok(header) = BlockHeaderLondon::deserialize(buf) {
Ok(header.into())
} else {
BlockHeaderPreLondon::deserialize(buf).map(Into::into)
}
}
}

impl BlockHeader {
pub fn extra_data(&self) -> H256 {
let mut data = [0u8; 32];
Expand All @@ -222,6 +331,9 @@ impl BlockHeader {
stream.append(&self.timestamp);
stream.append(&self.extra_data);

#[cfg(feature = "eip1559")]
stream.append(&self.base_fee_per_gas);

if !partial {
stream.append(&self.mix_hash);
stream.append(&self.nonce);
Expand Down Expand Up @@ -253,6 +365,8 @@ impl RlpDecodable for BlockHeader {
extra_data: serialized.val_at(12)?,
mix_hash: serialized.val_at(13)?,
nonce: serialized.val_at(14)?,
#[cfg(feature = "eip1559")]
base_fee_per_gas: serialized.val_at(15)?,
hash: Some(near_keccak256(serialized.as_raw()).into()),
partial_hash: None,
};
Expand Down Expand Up @@ -301,14 +415,50 @@ impl rlp::Encodable for LogEntry {

// Receipt Header

#[derive(Debug, Clone, PartialEq, Eq, RlpEncodableDerive, RlpDecodableDerive)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Receipt {
pub status: bool,
pub gas_used: U256,
pub log_bloom: Bloom,
pub logs: Vec<LogEntry>,
}

impl rlp::Decodable for Receipt {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
let mut view = rlp.as_raw();

// https://eips.ethereum.org/EIPS/eip-2718
if let Some(&byte) = view.first() {
// https://eips.ethereum.org/EIPS/eip-2718#receipts
// If the first byte is between 0 and 0x7f it is an envelop receipt
if byte <= 0x7f {
view = &view[1..];
}
}

rlp::decode::<RlpDeriveReceipt>(view).map(Into::into)
}
}

#[derive(RlpDecodableDerive)]
pub struct RlpDeriveReceipt {
pub status: bool,
pub gas_used: U256,
pub log_bloom: Bloom,
pub logs: Vec<LogEntry>,
}

impl From<RlpDeriveReceipt> for Receipt {
fn from(receipt: RlpDeriveReceipt) -> Self {
Self {
status: receipt.status,
gas_used: receipt.gas_used,
log_bloom: receipt.log_bloom,
logs: receipt.logs,
}
}
}

pub fn near_sha256(data: &[u8]) -> [u8; 32] {
let mut buffer = [0u8; 32];
buffer.copy_from_slice(&near_sdk::env::sha256(data).as_slice());
Expand Down
Binary file modified contracts/near/res/eth_client.wasm
Binary file not shown.
Binary file modified contracts/near/res/eth_prover.wasm
Binary file not shown.
Loading

0 comments on commit fe6ed9e

Please sign in to comment.