Last active
February 11, 2022 22:46
-
-
Save mfornet/bedc71fe0d0122540bb07718f76b713b to your computer and use it in GitHub Desktop.
Macros expanded for rainbow bridge contracts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(prelude_import)] | |
#[prelude_import] | |
use std::prelude::rust_2018::*; | |
#[macro_use] | |
extern crate std; | |
use borsh::{BorshDeserialize, BorshSerialize}; | |
use eth_types::*; | |
use near_plugins::{only, pause, FullAccessKeyFallback, Ownable, Pausable, Upgradable}; | |
use near_sdk::collections::UnorderedMap; | |
use near_sdk::AccountId; | |
use near_sdk::{env, near_bindgen, PanicOnDefault}; | |
pub struct DoubleNodeWithMerkleProof { | |
pub dag_nodes: Vec<H512>, | |
pub proof: Vec<H128>, | |
} | |
#[automatically_derived] | |
#[allow(unused_qualifications)] | |
impl ::core::default::Default for DoubleNodeWithMerkleProof { | |
#[inline] | |
fn default() -> DoubleNodeWithMerkleProof { | |
DoubleNodeWithMerkleProof { | |
dag_nodes: ::core::default::Default::default(), | |
proof: ::core::default::Default::default(), | |
} | |
} | |
} | |
#[automatically_derived] | |
#[allow(unused_qualifications)] | |
impl ::core::fmt::Debug for DoubleNodeWithMerkleProof { | |
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { | |
match *self { | |
DoubleNodeWithMerkleProof { | |
dag_nodes: ref __self_0_0, | |
proof: ref __self_0_1, | |
} => { | |
let debug_trait_builder = | |
&mut ::core::fmt::Formatter::debug_struct(f, "DoubleNodeWithMerkleProof"); | |
let _ = ::core::fmt::DebugStruct::field( | |
debug_trait_builder, | |
"dag_nodes", | |
&&(*__self_0_0), | |
); | |
let _ = | |
::core::fmt::DebugStruct::field(debug_trait_builder, "proof", &&(*__self_0_1)); | |
::core::fmt::DebugStruct::finish(debug_trait_builder) | |
} | |
} | |
} | |
} | |
#[automatically_derived] | |
#[allow(unused_qualifications)] | |
impl ::core::clone::Clone for DoubleNodeWithMerkleProof { | |
#[inline] | |
fn clone(&self) -> DoubleNodeWithMerkleProof { | |
match *self { | |
DoubleNodeWithMerkleProof { | |
dag_nodes: ref __self_0_0, | |
proof: ref __self_0_1, | |
} => DoubleNodeWithMerkleProof { | |
dag_nodes: ::core::clone::Clone::clone(&(*__self_0_0)), | |
proof: ::core::clone::Clone::clone(&(*__self_0_1)), | |
}, | |
} | |
} | |
} | |
impl borsh::de::BorshDeserialize for DoubleNodeWithMerkleProof | |
where | |
Vec<H512>: borsh::BorshDeserialize, | |
Vec<H128>: borsh::BorshDeserialize, | |
{ | |
fn deserialize(buf: &mut &[u8]) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | |
Ok(Self { | |
dag_nodes: borsh::BorshDeserialize::deserialize(buf)?, | |
proof: borsh::BorshDeserialize::deserialize(buf)?, | |
}) | |
} | |
} | |
impl borsh::ser::BorshSerialize for DoubleNodeWithMerkleProof | |
where | |
Vec<H512>: borsh::ser::BorshSerialize, | |
Vec<H128>: borsh::ser::BorshSerialize, | |
{ | |
fn serialize<W: borsh::maybestd::io::Write>( | |
&self, | |
writer: &mut W, | |
) -> ::core::result::Result<(), borsh::maybestd::io::Error> { | |
borsh::BorshSerialize::serialize(&self.dag_nodes, writer)?; | |
borsh::BorshSerialize::serialize(&self.proof, writer)?; | |
Ok(()) | |
} | |
} | |
impl DoubleNodeWithMerkleProof { | |
fn truncate_to_h128(arr: H256) -> H128 { | |
let mut data = [0u8; 16]; | |
data.copy_from_slice(&(arr.0).0[16..]); | |
H128(data.into()) | |
} | |
fn hash_h128(l: H128, r: H128) -> H128 { | |
let mut data = [0u8; 64]; | |
data[16..32].copy_from_slice(&(l.0).0); | |
data[48..64].copy_from_slice(&(r.0).0); | |
Self::truncate_to_h128(near_sha256(&data).into()) | |
} | |
pub fn apply_merkle_proof(&self, index: u64) -> H128 { | |
let mut data = [0u8; 128]; | |
data[..64].copy_from_slice(&(self.dag_nodes[0].0).0); | |
data[64..].copy_from_slice(&(self.dag_nodes[1].0).0); | |
let mut leaf = Self::truncate_to_h128(near_sha256(&data).into()); | |
for i in 0..self.proof.len() { | |
if (index >> i as u64) % 2 == 0 { | |
leaf = Self::hash_h128(leaf, self.proof[i]); | |
} else { | |
leaf = Self::hash_h128(self.proof[i], leaf); | |
} | |
} | |
leaf | |
} | |
} | |
/// Minimal information about a header. | |
pub struct HeaderInfo { | |
pub total_difficulty: U256, | |
pub parent_hash: H256, | |
pub number: u64, | |
} | |
#[automatically_derived] | |
#[allow(unused_qualifications)] | |
impl ::core::default::Default for HeaderInfo { | |
#[inline] | |
fn default() -> HeaderInfo { | |
HeaderInfo { | |
total_difficulty: ::core::default::Default::default(), | |
parent_hash: ::core::default::Default::default(), | |
number: ::core::default::Default::default(), | |
} | |
} | |
} | |
impl borsh::de::BorshDeserialize for HeaderInfo | |
where | |
U256: borsh::BorshDeserialize, | |
H256: borsh::BorshDeserialize, | |
u64: borsh::BorshDeserialize, | |
{ | |
fn deserialize(buf: &mut &[u8]) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | |
Ok(Self { | |
total_difficulty: borsh::BorshDeserialize::deserialize(buf)?, | |
parent_hash: borsh::BorshDeserialize::deserialize(buf)?, | |
number: borsh::BorshDeserialize::deserialize(buf)?, | |
}) | |
} | |
} | |
impl borsh::ser::BorshSerialize for HeaderInfo | |
where | |
U256: borsh::ser::BorshSerialize, | |
H256: borsh::ser::BorshSerialize, | |
u64: borsh::ser::BorshSerialize, | |
{ | |
fn serialize<W: borsh::maybestd::io::Write>( | |
&self, | |
writer: &mut W, | |
) -> ::core::result::Result<(), borsh::maybestd::io::Error> { | |
borsh::BorshSerialize::serialize(&self.total_difficulty, writer)?; | |
borsh::BorshSerialize::serialize(&self.parent_hash, writer)?; | |
borsh::BorshSerialize::serialize(&self.number, writer)?; | |
Ok(()) | |
} | |
} | |
pub struct EthClient { | |
/// Whether client validates the PoW when accepting the header. Should only be set to `false` | |
/// for debugging, testing, diagnostic purposes when used with Ganache or in PoA testnets | |
validate_ethash: bool, | |
/// The epoch from which the DAG merkle roots start. | |
dags_start_epoch: u64, | |
/// DAG merkle roots for the next several years. | |
dags_merkle_roots: Vec<H128>, | |
/// Hash of the header that has the highest cumulative difficulty. The current head of the | |
/// canonical chain. | |
best_header_hash: H256, | |
/// We store the hashes of the blocks for the past `hashes_gc_threshold` headers. | |
/// Events that happen past this threshold cannot be verified by the client. | |
/// It is desirable that this number is larger than 7 days worth of headers, which is roughly | |
/// 40k Ethereum blocks. So this number should be 40k in production. | |
hashes_gc_threshold: u64, | |
/// We store full information about the headers for the past `finalized_gc_threshold` blocks. | |
/// This is required to be able to adjust the canonical chain when the fork switch happens. | |
/// The commonly used number is 500 blocks, so this number should be 500 in production. | |
finalized_gc_threshold: u64, | |
/// Number of confirmations that applications can use to consider the transaction safe. | |
/// For most use cases 25 should be enough, for super safe cases it should be 500. | |
num_confirmations: u64, | |
/// Hashes of the canonical chain mapped to their numbers. Stores up to `hashes_gc_threshold` | |
/// entries. | |
/// header number -> header hash | |
canonical_header_hashes: UnorderedMap<u64, H256>, | |
/// All known header hashes. Stores up to `finalized_gc_threshold`. | |
/// header number -> hashes of all headers with this number. | |
all_header_hashes: UnorderedMap<u64, Vec<H256>>, | |
/// Known headers. Stores up to `finalized_gc_threshold`. | |
headers: UnorderedMap<H256, BlockHeader>, | |
/// Minimal information about the headers, like cumulative difficulty. Stores up to | |
/// `finalized_gc_threshold`. | |
infos: UnorderedMap<H256, HeaderInfo>, | |
/// If set, block header added by trusted signer will skip validation and added by | |
/// others will be immediately rejected, used in PoA testnets | |
trusted_signer: Option<AccountId>, | |
__paused: u128, | |
} | |
impl borsh::de::BorshDeserialize for EthClient | |
where | |
bool: borsh::BorshDeserialize, | |
u64: borsh::BorshDeserialize, | |
Vec<H128>: borsh::BorshDeserialize, | |
H256: borsh::BorshDeserialize, | |
u64: borsh::BorshDeserialize, | |
u64: borsh::BorshDeserialize, | |
u64: borsh::BorshDeserialize, | |
UnorderedMap<u64, H256>: borsh::BorshDeserialize, | |
UnorderedMap<u64, Vec<H256>>: borsh::BorshDeserialize, | |
UnorderedMap<H256, BlockHeader>: borsh::BorshDeserialize, | |
UnorderedMap<H256, HeaderInfo>: borsh::BorshDeserialize, | |
Option<AccountId>: borsh::BorshDeserialize, | |
u128: borsh::BorshDeserialize, | |
{ | |
fn deserialize(buf: &mut &[u8]) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | |
Ok(Self { | |
validate_ethash: borsh::BorshDeserialize::deserialize(buf)?, | |
dags_start_epoch: borsh::BorshDeserialize::deserialize(buf)?, | |
dags_merkle_roots: borsh::BorshDeserialize::deserialize(buf)?, | |
best_header_hash: borsh::BorshDeserialize::deserialize(buf)?, | |
hashes_gc_threshold: borsh::BorshDeserialize::deserialize(buf)?, | |
finalized_gc_threshold: borsh::BorshDeserialize::deserialize(buf)?, | |
num_confirmations: borsh::BorshDeserialize::deserialize(buf)?, | |
canonical_header_hashes: borsh::BorshDeserialize::deserialize(buf)?, | |
all_header_hashes: borsh::BorshDeserialize::deserialize(buf)?, | |
headers: borsh::BorshDeserialize::deserialize(buf)?, | |
infos: borsh::BorshDeserialize::deserialize(buf)?, | |
trusted_signer: borsh::BorshDeserialize::deserialize(buf)?, | |
__paused: borsh::BorshDeserialize::deserialize(buf)?, | |
}) | |
} | |
} | |
impl borsh::ser::BorshSerialize for EthClient | |
where | |
bool: borsh::ser::BorshSerialize, | |
u64: borsh::ser::BorshSerialize, | |
Vec<H128>: borsh::ser::BorshSerialize, | |
H256: borsh::ser::BorshSerialize, | |
u64: borsh::ser::BorshSerialize, | |
u64: borsh::ser::BorshSerialize, | |
u64: borsh::ser::BorshSerialize, | |
UnorderedMap<u64, H256>: borsh::ser::BorshSerialize, | |
UnorderedMap<u64, Vec<H256>>: borsh::ser::BorshSerialize, | |
UnorderedMap<H256, BlockHeader>: borsh::ser::BorshSerialize, | |
UnorderedMap<H256, HeaderInfo>: borsh::ser::BorshSerialize, | |
Option<AccountId>: borsh::ser::BorshSerialize, | |
u128: borsh::ser::BorshSerialize, | |
{ | |
fn serialize<W: borsh::maybestd::io::Write>( | |
&self, | |
writer: &mut W, | |
) -> ::core::result::Result<(), borsh::maybestd::io::Error> { | |
borsh::BorshSerialize::serialize(&self.validate_ethash, writer)?; | |
borsh::BorshSerialize::serialize(&self.dags_start_epoch, writer)?; | |
borsh::BorshSerialize::serialize(&self.dags_merkle_roots, writer)?; | |
borsh::BorshSerialize::serialize(&self.best_header_hash, writer)?; | |
borsh::BorshSerialize::serialize(&self.hashes_gc_threshold, writer)?; | |
borsh::BorshSerialize::serialize(&self.finalized_gc_threshold, writer)?; | |
borsh::BorshSerialize::serialize(&self.num_confirmations, writer)?; | |
borsh::BorshSerialize::serialize(&self.canonical_header_hashes, writer)?; | |
borsh::BorshSerialize::serialize(&self.all_header_hashes, writer)?; | |
borsh::BorshSerialize::serialize(&self.headers, writer)?; | |
borsh::BorshSerialize::serialize(&self.infos, writer)?; | |
borsh::BorshSerialize::serialize(&self.trusted_signer, writer)?; | |
borsh::BorshSerialize::serialize(&self.__paused, writer)?; | |
Ok(()) | |
} | |
} | |
impl Default for EthClient { | |
fn default() -> Self { | |
near_sdk::env::panic_str("The contract is not initialized"); | |
} | |
} | |
impl Ownable for EthClient { | |
fn owner_storage_key(&self) -> Vec<u8> { | |
("__OWNER__").as_bytes().to_vec() | |
} | |
fn owner_get(&self) -> Option<::near_sdk::AccountId> { | |
::near_sdk::env::storage_read(&self.owner_storage_key()).map(|owner_bytes| { | |
let owner_raw = String::from_utf8(owner_bytes).expect("Ownable: Invalid string format"); | |
std::convert::TryInto::try_into(owner_raw).expect("Ownable: Invalid account id") | |
}) | |
} | |
fn owner_set(&mut self, owner: Option<::near_sdk::AccountId>) { | |
let current_owner = self.owner_get(); | |
if let Some(owner) = current_owner.as_ref() { | |
{ | |
match (&&::near_sdk::env::predecessor_account_id(), &owner) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
let kind = ::core::panicking::AssertKind::Eq; | |
::core::panicking::assert_failed( | |
kind, | |
&*left_val, | |
&*right_val, | |
::core::option::Option::Some(::core::fmt::Arguments::new_v1( | |
&["Ownable: Only owner can update current owner"], | |
&[], | |
)), | |
); | |
} | |
} | |
} | |
}; | |
} else { | |
{ | |
match ( | |
&::near_sdk::env::predecessor_account_id(), | |
&::near_sdk::env::current_account_id(), | |
) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
let kind = ::core::panicking::AssertKind::Eq; | |
::core::panicking::assert_failed( | |
kind, | |
&*left_val, | |
&*right_val, | |
::core::option::Option::Some(::core::fmt::Arguments::new_v1( | |
&["Ownable: Owner not set. Only self can set the owner"], | |
&[], | |
)), | |
); | |
} | |
} | |
} | |
}; | |
} | |
::near_sdk::env::log_str( | |
near_plugins::events::AsEvent::event(&near_plugins::ownable::OwnershipTransferred { | |
previous_owner: current_owner, | |
new_owner: owner.clone(), | |
}) | |
.as_ref(), | |
); | |
match owner.as_ref() { | |
Some(owner) => { | |
::near_sdk::env::storage_write(&self.owner_storage_key(), owner.as_ref().as_bytes()) | |
} | |
None => ::near_sdk::env::storage_remove(&self.owner_storage_key()), | |
}; | |
} | |
fn owner_is(&self) -> bool { | |
self.owner_get().map_or(false, |owner| { | |
owner == ::near_sdk::env::predecessor_account_id() | |
}) | |
} | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn owner_storage_key() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.owner_storage_key(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn owner_get() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.owner_get(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn owner_set() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method owner_set doesn\'t accept deposit"); | |
} | |
#[serde(crate = "near_sdk::serde")] | |
struct Input { | |
owner: Option<::near_sdk::AccountId>, | |
} | |
#[doc(hidden)] | |
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] | |
const _IMPL_DESERIALIZE_FOR_Input: () = { | |
use near_sdk::serde as _serde; | |
#[automatically_derived] | |
impl<'de> near_sdk::serde::Deserialize<'de> for Input { | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> near_sdk::serde::export::Result<Self, __D::Error> | |
where | |
__D: near_sdk::serde::Deserializer<'de>, | |
{ | |
#[allow(non_camel_case_types)] | |
enum __Field { | |
__field0, | |
__ignore, | |
} | |
struct __FieldVisitor; | |
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { | |
type Value = __Field; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "field identifier") | |
} | |
fn visit_u64<__E>( | |
self, | |
__value: u64, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
0u64 => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Err(_serde::de::Error::invalid_value( | |
_serde::de::Unexpected::Unsigned(__value), | |
&"field index 0 <= i < 1", | |
)), | |
} | |
} | |
fn visit_str<__E>( | |
self, | |
__value: &str, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
"owner" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
fn visit_bytes<__E>( | |
self, | |
__value: &[u8], | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
b"owner" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
} | |
impl<'de> _serde::Deserialize<'de> for __Field { | |
#[inline] | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> _serde::export::Result<Self, __D::Error> | |
where | |
__D: _serde::Deserializer<'de>, | |
{ | |
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) | |
} | |
} | |
struct __Visitor<'de> { | |
marker: _serde::export::PhantomData<Input>, | |
lifetime: _serde::export::PhantomData<&'de ()>, | |
} | |
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { | |
type Value = Input; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "struct Input") | |
} | |
#[inline] | |
fn visit_seq<__A>( | |
self, | |
mut __seq: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::SeqAccess<'de>, | |
{ | |
let __field0 = match match _serde::de::SeqAccess::next_element::< | |
Option<::near_sdk::AccountId>, | |
>(&mut __seq) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} { | |
_serde::export::Some(__value) => __value, | |
_serde::export::None => { | |
return _serde::export::Err(_serde::de::Error::invalid_length( | |
0usize, | |
&"struct Input with 1 element", | |
)); | |
} | |
}; | |
_serde::export::Ok(Input { owner: __field0 }) | |
} | |
#[inline] | |
fn visit_map<__A>( | |
self, | |
mut __map: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::MapAccess<'de>, | |
{ | |
let mut __field0: _serde::export::Option<Option<::near_sdk::AccountId>> = | |
_serde::export::None; | |
while let _serde::export::Some(__key) = | |
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
{ | |
match __key { | |
__Field::__field0 => { | |
if _serde::export::Option::is_some(&__field0) { | |
return _serde::export::Err( | |
<__A::Error as _serde::de::Error>::duplicate_field( | |
"owner", | |
), | |
); | |
} | |
__field0 = _serde::export::Some( | |
match _serde::de::MapAccess::next_value::< | |
Option<::near_sdk::AccountId>, | |
>(&mut __map) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
); | |
} | |
_ => { | |
let _ = match _serde::de::MapAccess::next_value::< | |
_serde::de::IgnoredAny, | |
>(&mut __map) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}; | |
} | |
} | |
} | |
let __field0 = match __field0 { | |
_serde::export::Some(__field0) => __field0, | |
_serde::export::None => { | |
match _serde::private::de::missing_field("owner") { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
} | |
}; | |
_serde::export::Ok(Input { owner: __field0 }) | |
} | |
} | |
const FIELDS: &'static [&'static str] = &["owner"]; | |
_serde::Deserializer::deserialize_struct( | |
__deserializer, | |
"Input", | |
FIELDS, | |
__Visitor { | |
marker: _serde::export::PhantomData::<Input>, | |
lifetime: _serde::export::PhantomData, | |
}, | |
) | |
} | |
} | |
}; | |
let Input { owner }: Input = near_sdk::serde_json::from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from JSON."); | |
let mut contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
contract.owner_set(owner); | |
near_sdk::env::state_write(&contract); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn owner_is() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.owner_is(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
impl Pausable for EthClient { | |
fn pa_storage_key(&self) -> Vec<u8> { | |
("__PAUSE__").as_bytes().to_vec() | |
} | |
fn pa_is_paused(&self, key: String) -> bool { | |
self.pa_all_paused() | |
.map(|keys| keys.contains(&key) || keys.contains("ALL")) | |
.unwrap_or(false) | |
} | |
fn pa_all_paused(&self) -> Option<std::collections::HashSet<String>> { | |
::near_sdk::env::storage_read(self.pa_storage_key().as_ref()).map(|value| { | |
std::collections::HashSet::try_from_slice(value.as_ref()) | |
.expect("Pausable: Invalid format for paused keys") | |
}) | |
} | |
fn pa_pause_feature(&mut self, key: String) { | |
if !self.owner_is() { | |
{ | |
::std::rt::begin_panic("Ownable: Method must be called from owner") | |
} | |
}; | |
let mut paused_keys = self.pa_all_paused().unwrap_or_default(); | |
paused_keys.insert(key.clone()); | |
::near_sdk::env::log_str( | |
near_plugins::events::AsEvent::event(&near_plugins::pausable::Pause { | |
by: ::near_sdk::env::predecessor_account_id(), | |
key, | |
}) | |
.as_ref(), | |
); | |
::near_sdk::env::storage_write( | |
self.pa_storage_key().as_ref(), | |
paused_keys | |
.try_to_vec() | |
.expect("Pausable: Unexpected error serializing keys") | |
.as_ref(), | |
); | |
} | |
fn pa_unpause_feature(&mut self, key: String) { | |
if !self.owner_is() { | |
{ | |
::std::rt::begin_panic("Ownable: Method must be called from owner") | |
} | |
}; | |
let mut paused_keys = self.pa_all_paused().unwrap_or_default(); | |
paused_keys.remove(&key); | |
::near_sdk::env::log_str( | |
near_plugins::events::AsEvent::event(&near_plugins::pausable::Unpause { | |
by: ::near_sdk::env::predecessor_account_id(), | |
key, | |
}) | |
.as_ref(), | |
); | |
if paused_keys.is_empty() { | |
::near_sdk::env::storage_remove(self.pa_storage_key().as_ref()); | |
} else { | |
::near_sdk::env::storage_write( | |
self.pa_storage_key().as_ref(), | |
paused_keys | |
.try_to_vec() | |
.expect("Pausable: Unexpected error serializing keys") | |
.as_ref(), | |
); | |
} | |
} | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn pa_storage_key() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.pa_storage_key(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn pa_is_paused() { | |
near_sdk::env::setup_panic_hook(); | |
#[serde(crate = "near_sdk::serde")] | |
struct Input { | |
key: String, | |
} | |
#[doc(hidden)] | |
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] | |
const _IMPL_DESERIALIZE_FOR_Input: () = { | |
use near_sdk::serde as _serde; | |
#[automatically_derived] | |
impl<'de> near_sdk::serde::Deserialize<'de> for Input { | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> near_sdk::serde::export::Result<Self, __D::Error> | |
where | |
__D: near_sdk::serde::Deserializer<'de>, | |
{ | |
#[allow(non_camel_case_types)] | |
enum __Field { | |
__field0, | |
__ignore, | |
} | |
struct __FieldVisitor; | |
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { | |
type Value = __Field; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "field identifier") | |
} | |
fn visit_u64<__E>( | |
self, | |
__value: u64, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
0u64 => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Err(_serde::de::Error::invalid_value( | |
_serde::de::Unexpected::Unsigned(__value), | |
&"field index 0 <= i < 1", | |
)), | |
} | |
} | |
fn visit_str<__E>( | |
self, | |
__value: &str, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
"key" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
fn visit_bytes<__E>( | |
self, | |
__value: &[u8], | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
b"key" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
} | |
impl<'de> _serde::Deserialize<'de> for __Field { | |
#[inline] | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> _serde::export::Result<Self, __D::Error> | |
where | |
__D: _serde::Deserializer<'de>, | |
{ | |
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) | |
} | |
} | |
struct __Visitor<'de> { | |
marker: _serde::export::PhantomData<Input>, | |
lifetime: _serde::export::PhantomData<&'de ()>, | |
} | |
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { | |
type Value = Input; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "struct Input") | |
} | |
#[inline] | |
fn visit_seq<__A>( | |
self, | |
mut __seq: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::SeqAccess<'de>, | |
{ | |
let __field0 = | |
match match _serde::de::SeqAccess::next_element::<String>(&mut __seq) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} { | |
_serde::export::Some(__value) => __value, | |
_serde::export::None => { | |
return _serde::export::Err(_serde::de::Error::invalid_length( | |
0usize, | |
&"struct Input with 1 element", | |
)); | |
} | |
}; | |
_serde::export::Ok(Input { key: __field0 }) | |
} | |
#[inline] | |
fn visit_map<__A>( | |
self, | |
mut __map: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::MapAccess<'de>, | |
{ | |
let mut __field0: _serde::export::Option<String> = _serde::export::None; | |
while let _serde::export::Some(__key) = | |
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
{ | |
match __key { | |
__Field::__field0 => { | |
if _serde::export::Option::is_some(&__field0) { | |
return _serde::export::Err( | |
<__A::Error as _serde::de::Error>::duplicate_field( | |
"key", | |
), | |
); | |
} | |
__field0 = _serde::export::Some( | |
match _serde::de::MapAccess::next_value::<String>( | |
&mut __map, | |
) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
); | |
} | |
_ => { | |
let _ = match _serde::de::MapAccess::next_value::< | |
_serde::de::IgnoredAny, | |
>(&mut __map) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}; | |
} | |
} | |
} | |
let __field0 = match __field0 { | |
_serde::export::Some(__field0) => __field0, | |
_serde::export::None => match _serde::private::de::missing_field("key") | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
}; | |
_serde::export::Ok(Input { key: __field0 }) | |
} | |
} | |
const FIELDS: &'static [&'static str] = &["key"]; | |
_serde::Deserializer::deserialize_struct( | |
__deserializer, | |
"Input", | |
FIELDS, | |
__Visitor { | |
marker: _serde::export::PhantomData::<Input>, | |
lifetime: _serde::export::PhantomData, | |
}, | |
) | |
} | |
} | |
}; | |
let Input { key }: Input = near_sdk::serde_json::from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from JSON."); | |
let contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.pa_is_paused(key); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn pa_all_paused() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.pa_all_paused(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn pa_pause_feature() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method pa_pause_feature doesn\'t accept deposit"); | |
} | |
#[serde(crate = "near_sdk::serde")] | |
struct Input { | |
key: String, | |
} | |
#[doc(hidden)] | |
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] | |
const _IMPL_DESERIALIZE_FOR_Input: () = { | |
use near_sdk::serde as _serde; | |
#[automatically_derived] | |
impl<'de> near_sdk::serde::Deserialize<'de> for Input { | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> near_sdk::serde::export::Result<Self, __D::Error> | |
where | |
__D: near_sdk::serde::Deserializer<'de>, | |
{ | |
#[allow(non_camel_case_types)] | |
enum __Field { | |
__field0, | |
__ignore, | |
} | |
struct __FieldVisitor; | |
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { | |
type Value = __Field; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "field identifier") | |
} | |
fn visit_u64<__E>( | |
self, | |
__value: u64, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
0u64 => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Err(_serde::de::Error::invalid_value( | |
_serde::de::Unexpected::Unsigned(__value), | |
&"field index 0 <= i < 1", | |
)), | |
} | |
} | |
fn visit_str<__E>( | |
self, | |
__value: &str, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
"key" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
fn visit_bytes<__E>( | |
self, | |
__value: &[u8], | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
b"key" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
} | |
impl<'de> _serde::Deserialize<'de> for __Field { | |
#[inline] | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> _serde::export::Result<Self, __D::Error> | |
where | |
__D: _serde::Deserializer<'de>, | |
{ | |
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) | |
} | |
} | |
struct __Visitor<'de> { | |
marker: _serde::export::PhantomData<Input>, | |
lifetime: _serde::export::PhantomData<&'de ()>, | |
} | |
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { | |
type Value = Input; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "struct Input") | |
} | |
#[inline] | |
fn visit_seq<__A>( | |
self, | |
mut __seq: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::SeqAccess<'de>, | |
{ | |
let __field0 = | |
match match _serde::de::SeqAccess::next_element::<String>(&mut __seq) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} { | |
_serde::export::Some(__value) => __value, | |
_serde::export::None => { | |
return _serde::export::Err(_serde::de::Error::invalid_length( | |
0usize, | |
&"struct Input with 1 element", | |
)); | |
} | |
}; | |
_serde::export::Ok(Input { key: __field0 }) | |
} | |
#[inline] | |
fn visit_map<__A>( | |
self, | |
mut __map: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::MapAccess<'de>, | |
{ | |
let mut __field0: _serde::export::Option<String> = _serde::export::None; | |
while let _serde::export::Some(__key) = | |
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
{ | |
match __key { | |
__Field::__field0 => { | |
if _serde::export::Option::is_some(&__field0) { | |
return _serde::export::Err( | |
<__A::Error as _serde::de::Error>::duplicate_field( | |
"key", | |
), | |
); | |
} | |
__field0 = _serde::export::Some( | |
match _serde::de::MapAccess::next_value::<String>( | |
&mut __map, | |
) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
); | |
} | |
_ => { | |
let _ = match _serde::de::MapAccess::next_value::< | |
_serde::de::IgnoredAny, | |
>(&mut __map) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}; | |
} | |
} | |
} | |
let __field0 = match __field0 { | |
_serde::export::Some(__field0) => __field0, | |
_serde::export::None => match _serde::private::de::missing_field("key") | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
}; | |
_serde::export::Ok(Input { key: __field0 }) | |
} | |
} | |
const FIELDS: &'static [&'static str] = &["key"]; | |
_serde::Deserializer::deserialize_struct( | |
__deserializer, | |
"Input", | |
FIELDS, | |
__Visitor { | |
marker: _serde::export::PhantomData::<Input>, | |
lifetime: _serde::export::PhantomData, | |
}, | |
) | |
} | |
} | |
}; | |
let Input { key }: Input = near_sdk::serde_json::from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from JSON."); | |
let mut contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
contract.pa_pause_feature(key); | |
near_sdk::env::state_write(&contract); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn pa_unpause_feature() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method pa_unpause_feature doesn\'t accept deposit"); | |
} | |
#[serde(crate = "near_sdk::serde")] | |
struct Input { | |
key: String, | |
} | |
#[doc(hidden)] | |
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] | |
const _IMPL_DESERIALIZE_FOR_Input: () = { | |
use near_sdk::serde as _serde; | |
#[automatically_derived] | |
impl<'de> near_sdk::serde::Deserialize<'de> for Input { | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> near_sdk::serde::export::Result<Self, __D::Error> | |
where | |
__D: near_sdk::serde::Deserializer<'de>, | |
{ | |
#[allow(non_camel_case_types)] | |
enum __Field { | |
__field0, | |
__ignore, | |
} | |
struct __FieldVisitor; | |
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { | |
type Value = __Field; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "field identifier") | |
} | |
fn visit_u64<__E>( | |
self, | |
__value: u64, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
0u64 => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Err(_serde::de::Error::invalid_value( | |
_serde::de::Unexpected::Unsigned(__value), | |
&"field index 0 <= i < 1", | |
)), | |
} | |
} | |
fn visit_str<__E>( | |
self, | |
__value: &str, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
"key" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
fn visit_bytes<__E>( | |
self, | |
__value: &[u8], | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
b"key" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
} | |
impl<'de> _serde::Deserialize<'de> for __Field { | |
#[inline] | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> _serde::export::Result<Self, __D::Error> | |
where | |
__D: _serde::Deserializer<'de>, | |
{ | |
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) | |
} | |
} | |
struct __Visitor<'de> { | |
marker: _serde::export::PhantomData<Input>, | |
lifetime: _serde::export::PhantomData<&'de ()>, | |
} | |
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { | |
type Value = Input; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "struct Input") | |
} | |
#[inline] | |
fn visit_seq<__A>( | |
self, | |
mut __seq: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::SeqAccess<'de>, | |
{ | |
let __field0 = | |
match match _serde::de::SeqAccess::next_element::<String>(&mut __seq) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} { | |
_serde::export::Some(__value) => __value, | |
_serde::export::None => { | |
return _serde::export::Err(_serde::de::Error::invalid_length( | |
0usize, | |
&"struct Input with 1 element", | |
)); | |
} | |
}; | |
_serde::export::Ok(Input { key: __field0 }) | |
} | |
#[inline] | |
fn visit_map<__A>( | |
self, | |
mut __map: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::MapAccess<'de>, | |
{ | |
let mut __field0: _serde::export::Option<String> = _serde::export::None; | |
while let _serde::export::Some(__key) = | |
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
{ | |
match __key { | |
__Field::__field0 => { | |
if _serde::export::Option::is_some(&__field0) { | |
return _serde::export::Err( | |
<__A::Error as _serde::de::Error>::duplicate_field( | |
"key", | |
), | |
); | |
} | |
__field0 = _serde::export::Some( | |
match _serde::de::MapAccess::next_value::<String>( | |
&mut __map, | |
) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
); | |
} | |
_ => { | |
let _ = match _serde::de::MapAccess::next_value::< | |
_serde::de::IgnoredAny, | |
>(&mut __map) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}; | |
} | |
} | |
} | |
let __field0 = match __field0 { | |
_serde::export::Some(__field0) => __field0, | |
_serde::export::None => match _serde::private::de::missing_field("key") | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
}; | |
_serde::export::Ok(Input { key: __field0 }) | |
} | |
} | |
const FIELDS: &'static [&'static str] = &["key"]; | |
_serde::Deserializer::deserialize_struct( | |
__deserializer, | |
"Input", | |
FIELDS, | |
__Visitor { | |
marker: _serde::export::PhantomData::<Input>, | |
lifetime: _serde::export::PhantomData, | |
}, | |
) | |
} | |
} | |
}; | |
let Input { key }: Input = near_sdk::serde_json::from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from JSON."); | |
let mut contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
contract.pa_unpause_feature(key); | |
near_sdk::env::state_write(&contract); | |
} | |
impl Upgradable for EthClient { | |
fn up_storage_key(&self) -> Vec<u8> { | |
("__CODE__").as_bytes().to_vec() | |
} | |
fn up_stage_code(&mut self, code: Vec<u8>) { | |
if !self.owner_is() { | |
{ | |
::std::rt::begin_panic("Ownable: Method must be called from owner") | |
} | |
}; | |
if code.is_empty() { | |
near_sdk::env::storage_remove(self.up_storage_key().as_ref()); | |
} else { | |
near_sdk::env::storage_write(self.up_storage_key().as_ref(), code.as_ref()); | |
} | |
} | |
fn up_staged_code(&self) -> Option<Vec<u8>> { | |
near_sdk::env::storage_read(self.up_storage_key().as_ref()) | |
} | |
fn up_staged_code_hash(&self) -> Option<::near_sdk::CryptoHash> { | |
self.up_staged_code().map(|code| { | |
std::convert::TryInto::try_into(near_sdk::env::sha256(code.as_ref())).unwrap() | |
}) | |
} | |
fn up_deploy_code(&mut self) -> near_sdk::Promise { | |
if !self.owner_is() { | |
{ | |
::std::rt::begin_panic("Ownable: Method must be called from owner") | |
} | |
}; | |
near_sdk::Promise::new(near_sdk::env::current_account_id()) | |
.deploy_contract(self.up_staged_code().expect("Upgradable: No staged code")) | |
} | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn up_storage_key() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.up_storage_key(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn up_stage_code() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method up_stage_code doesn\'t accept deposit"); | |
} | |
struct Input { | |
code: Vec<u8>, | |
} | |
impl borsh::de::BorshDeserialize for Input | |
where | |
Vec<u8>: borsh::BorshDeserialize, | |
{ | |
fn deserialize( | |
buf: &mut &[u8], | |
) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | |
Ok(Self { | |
code: borsh::BorshDeserialize::deserialize(buf)?, | |
}) | |
} | |
} | |
let Input { code }: Input = near_sdk::borsh::BorshDeserialize::try_from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from Borsh."); | |
let mut contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
contract.up_stage_code(code); | |
near_sdk::env::state_write(&contract); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn up_staged_code() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.up_staged_code(); | |
let result = near_sdk::borsh::BorshSerialize::try_to_vec(&result) | |
.expect("Failed to serialize the return value using Borsh."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn up_staged_code_hash() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.up_staged_code_hash(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn up_deploy_code() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method up_deploy_code doesn\'t accept deposit"); | |
} | |
let mut contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.up_deploy_code(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
near_sdk::env::state_write(&contract); | |
} | |
impl FullAccessKeyFallback for EthClient { | |
fn attach_full_access_key(&mut self, public_key: ::near_sdk::PublicKey) -> near_sdk::Promise { | |
if !self.owner_is() { | |
{ | |
::std::rt::begin_panic("Ownable: Method must be called from owner") | |
} | |
}; | |
let current_account_id = ::near_sdk::env::current_account_id(); | |
::near_sdk::env::log_str( | |
near_plugins::events::AsEvent::event( | |
&near_plugins::full_access_key_fallback::FullAccessKeyAdded { | |
by: current_account_id.clone(), | |
public_key: public_key.clone(), | |
}, | |
) | |
.as_ref(), | |
); | |
::near_sdk::Promise::new(current_account_id).add_full_access_key(public_key) | |
} | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn attach_full_access_key() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method attach_full_access_key doesn\'t accept deposit"); | |
} | |
#[serde(crate = "near_sdk::serde")] | |
struct Input { | |
public_key: ::near_sdk::PublicKey, | |
} | |
#[doc(hidden)] | |
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] | |
const _IMPL_DESERIALIZE_FOR_Input: () = { | |
use near_sdk::serde as _serde; | |
#[automatically_derived] | |
impl<'de> near_sdk::serde::Deserialize<'de> for Input { | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> near_sdk::serde::export::Result<Self, __D::Error> | |
where | |
__D: near_sdk::serde::Deserializer<'de>, | |
{ | |
#[allow(non_camel_case_types)] | |
enum __Field { | |
__field0, | |
__ignore, | |
} | |
struct __FieldVisitor; | |
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { | |
type Value = __Field; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "field identifier") | |
} | |
fn visit_u64<__E>( | |
self, | |
__value: u64, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
0u64 => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Err(_serde::de::Error::invalid_value( | |
_serde::de::Unexpected::Unsigned(__value), | |
&"field index 0 <= i < 1", | |
)), | |
} | |
} | |
fn visit_str<__E>( | |
self, | |
__value: &str, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
"public_key" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
fn visit_bytes<__E>( | |
self, | |
__value: &[u8], | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
b"public_key" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
} | |
impl<'de> _serde::Deserialize<'de> for __Field { | |
#[inline] | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> _serde::export::Result<Self, __D::Error> | |
where | |
__D: _serde::Deserializer<'de>, | |
{ | |
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) | |
} | |
} | |
struct __Visitor<'de> { | |
marker: _serde::export::PhantomData<Input>, | |
lifetime: _serde::export::PhantomData<&'de ()>, | |
} | |
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { | |
type Value = Input; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "struct Input") | |
} | |
#[inline] | |
fn visit_seq<__A>( | |
self, | |
mut __seq: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::SeqAccess<'de>, | |
{ | |
let __field0 = match match _serde::de::SeqAccess::next_element::< | |
::near_sdk::PublicKey, | |
>(&mut __seq) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} { | |
_serde::export::Some(__value) => __value, | |
_serde::export::None => { | |
return _serde::export::Err(_serde::de::Error::invalid_length( | |
0usize, | |
&"struct Input with 1 element", | |
)); | |
} | |
}; | |
_serde::export::Ok(Input { | |
public_key: __field0, | |
}) | |
} | |
#[inline] | |
fn visit_map<__A>( | |
self, | |
mut __map: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::MapAccess<'de>, | |
{ | |
let mut __field0: _serde::export::Option<::near_sdk::PublicKey> = | |
_serde::export::None; | |
while let _serde::export::Some(__key) = | |
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
{ | |
match __key { | |
__Field::__field0 => { | |
if _serde::export::Option::is_some(&__field0) { | |
return _serde::export::Err( | |
<__A::Error as _serde::de::Error>::duplicate_field( | |
"public_key", | |
), | |
); | |
} | |
__field0 = _serde::export::Some( | |
match _serde::de::MapAccess::next_value::< | |
::near_sdk::PublicKey, | |
>(&mut __map) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
); | |
} | |
_ => { | |
let _ = match _serde::de::MapAccess::next_value::< | |
_serde::de::IgnoredAny, | |
>(&mut __map) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}; | |
} | |
} | |
} | |
let __field0 = match __field0 { | |
_serde::export::Some(__field0) => __field0, | |
_serde::export::None => { | |
match _serde::private::de::missing_field("public_key") { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
} | |
}; | |
_serde::export::Ok(Input { | |
public_key: __field0, | |
}) | |
} | |
} | |
const FIELDS: &'static [&'static str] = &["public_key"]; | |
_serde::Deserializer::deserialize_struct( | |
__deserializer, | |
"Input", | |
FIELDS, | |
__Visitor { | |
marker: _serde::export::PhantomData::<Input>, | |
lifetime: _serde::export::PhantomData, | |
}, | |
) | |
} | |
} | |
}; | |
let Input { public_key }: Input = near_sdk::serde_json::from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from JSON."); | |
let mut contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.attach_full_access_key(public_key); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
near_sdk::env::state_write(&contract); | |
} | |
impl EthClient { | |
pub fn init( | |
validate_ethash: bool, | |
dags_start_epoch: u64, | |
dags_merkle_roots: Vec<H128>, | |
first_header: Vec<u8>, | |
hashes_gc_threshold: u64, | |
finalized_gc_threshold: u64, | |
num_confirmations: u64, | |
trusted_signer: Option<AccountId>, | |
) -> Self { | |
let header: BlockHeader = rlp::decode(first_header.as_slice()).unwrap(); | |
let header_hash = header.hash.unwrap().clone(); | |
let header_number = header.number; | |
let mut res = Self { | |
validate_ethash, | |
dags_start_epoch, | |
dags_merkle_roots, | |
best_header_hash: header_hash.clone(), | |
hashes_gc_threshold, | |
finalized_gc_threshold, | |
num_confirmations, | |
canonical_header_hashes: UnorderedMap::new(b"c".to_vec()), | |
all_header_hashes: UnorderedMap::new(b"a".to_vec()), | |
headers: UnorderedMap::new(b"h".to_vec()), | |
infos: UnorderedMap::new(b"i".to_vec()), | |
trusted_signer, | |
__paused: Default::default(), | |
}; | |
res.canonical_header_hashes | |
.insert(&header_number, &header_hash); | |
res.all_header_hashes | |
.insert(&header_number, &<[_]>::into_vec(box [header_hash.clone()])); | |
res.headers.insert(&header_hash, &header); | |
res.infos.insert( | |
&header_hash, | |
&HeaderInfo { | |
total_difficulty: Default::default(), | |
parent_hash: Default::default(), | |
number: header_number, | |
}, | |
); | |
res | |
} | |
pub fn initialized() -> bool { | |
env::state_read::<EthClient>().is_some() | |
} | |
pub fn dag_merkle_root(&self, epoch: u64) -> H128 { | |
self.dags_merkle_roots[(&epoch - self.dags_start_epoch) as usize] | |
} | |
pub fn last_block_number(&self) -> u64 { | |
self.infos | |
.get(&self.best_header_hash) | |
.unwrap_or_default() | |
.number | |
} | |
/// Returns the block hash from the canonical chain. | |
pub fn block_hash(&self, index: u64) -> Option<H256> { | |
self.canonical_header_hashes.get(&index) | |
} | |
/// Returns all hashes known for that height. | |
pub fn known_hashes(&self, index: u64) -> Vec<H256> { | |
self.all_header_hashes.get(&index).unwrap_or_default() | |
} | |
/// Returns block hash and the number of confirmations. | |
pub fn block_hash_safe(&self, index: u64) -> Option<H256> { | |
let header_hash = self.block_hash(index)?; | |
let last_block_number = self.last_block_number(); | |
if index + self.num_confirmations > last_block_number { | |
None | |
} else { | |
Some(header_hash) | |
} | |
} | |
/// Add the block header to the client. | |
/// `block_header` -- RLP-encoded Ethereum header; | |
/// `dag_nodes` -- dag nodes with their merkle proofs. | |
pub fn add_block_header( | |
&mut self, | |
block_header: Vec<u8>, | |
dag_nodes: Vec<DoubleNodeWithMerkleProof>, | |
) { | |
let mut check_paused = true; | |
if check_paused { | |
if !!self.pa_is_paused("add_block_header".to_string()) { | |
{ | |
::std::rt::begin_panic("Pausable: Method is paused") | |
} | |
}; | |
} | |
env::log_str("Add block header"); | |
let header: BlockHeader = rlp::decode(block_header.as_slice()).unwrap(); | |
if let Some(trusted_signer) = &self.trusted_signer { | |
{ | |
match (&&env::signer_account_id(), &trusted_signer) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
let kind = ::core::panicking::AssertKind::Eq; | |
:: core :: panicking :: assert_failed (kind , & * left_val , & * right_val , :: core :: option :: Option :: Some (:: core :: fmt :: Arguments :: new_v1 (& ["Eth-client is deployed as trust mode, only trusted_signer can add a new header"] , & []))) ; | |
} | |
} | |
} | |
}; | |
} else { | |
let prev = self | |
.headers | |
.get(&header.parent_hash) | |
.expect("Parent header should be present to add a new header"); | |
if !self.verify_header(&header, &prev, &dag_nodes) { | |
{ | |
::std::rt::panic_fmt(::core::fmt::Arguments::new_v1( | |
&["The new header ", " should be valid"], | |
&[::core::fmt::ArgumentV1::new_display(&header.number)], | |
)) | |
} | |
}; | |
} | |
self.record_header(header); | |
} | |
pub fn update_trusted_signer(&mut self, trusted_signer: Option<AccountId>) { | |
if !self.owner_is() { | |
{ | |
::std::rt::begin_panic("Ownable: Method must be called from owner") | |
} | |
}; | |
self.trusted_signer = trusted_signer; | |
} | |
pub fn get_trusted_signer(&self) -> Option<AccountId> { | |
self.trusted_signer.clone() | |
} | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn init() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method init doesn\'t accept deposit"); | |
} | |
struct Input { | |
validate_ethash: bool, | |
dags_start_epoch: u64, | |
dags_merkle_roots: Vec<H128>, | |
first_header: Vec<u8>, | |
hashes_gc_threshold: u64, | |
finalized_gc_threshold: u64, | |
num_confirmations: u64, | |
trusted_signer: Option<AccountId>, | |
} | |
impl borsh::de::BorshDeserialize for Input | |
where | |
bool: borsh::BorshDeserialize, | |
u64: borsh::BorshDeserialize, | |
Vec<H128>: borsh::BorshDeserialize, | |
Vec<u8>: borsh::BorshDeserialize, | |
u64: borsh::BorshDeserialize, | |
u64: borsh::BorshDeserialize, | |
u64: borsh::BorshDeserialize, | |
Option<AccountId>: borsh::BorshDeserialize, | |
{ | |
fn deserialize( | |
buf: &mut &[u8], | |
) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | |
Ok(Self { | |
validate_ethash: borsh::BorshDeserialize::deserialize(buf)?, | |
dags_start_epoch: borsh::BorshDeserialize::deserialize(buf)?, | |
dags_merkle_roots: borsh::BorshDeserialize::deserialize(buf)?, | |
first_header: borsh::BorshDeserialize::deserialize(buf)?, | |
hashes_gc_threshold: borsh::BorshDeserialize::deserialize(buf)?, | |
finalized_gc_threshold: borsh::BorshDeserialize::deserialize(buf)?, | |
num_confirmations: borsh::BorshDeserialize::deserialize(buf)?, | |
trusted_signer: borsh::BorshDeserialize::deserialize(buf)?, | |
}) | |
} | |
} | |
let Input { | |
validate_ethash, | |
dags_start_epoch, | |
dags_merkle_roots, | |
first_header, | |
hashes_gc_threshold, | |
finalized_gc_threshold, | |
num_confirmations, | |
trusted_signer, | |
}: Input = near_sdk::borsh::BorshDeserialize::try_from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from Borsh."); | |
if near_sdk::env::state_exists() { | |
near_sdk::env::panic_str("The contract has already been initialized"); | |
} | |
let contract = EthClient::init( | |
validate_ethash, | |
dags_start_epoch, | |
dags_merkle_roots, | |
first_header, | |
hashes_gc_threshold, | |
finalized_gc_threshold, | |
num_confirmations, | |
trusted_signer, | |
); | |
near_sdk::env::state_write(&contract); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn initialized() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method initialized doesn\'t accept deposit"); | |
} | |
let result = EthClient::initialized(); | |
let result = near_sdk::borsh::BorshSerialize::try_to_vec(&result) | |
.expect("Failed to serialize the return value using Borsh."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn dag_merkle_root() { | |
near_sdk::env::setup_panic_hook(); | |
struct Input { | |
epoch: u64, | |
} | |
impl borsh::de::BorshDeserialize for Input | |
where | |
u64: borsh::BorshDeserialize, | |
{ | |
fn deserialize( | |
buf: &mut &[u8], | |
) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | |
Ok(Self { | |
epoch: borsh::BorshDeserialize::deserialize(buf)?, | |
}) | |
} | |
} | |
let Input { epoch }: Input = near_sdk::borsh::BorshDeserialize::try_from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from Borsh."); | |
let contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.dag_merkle_root(epoch); | |
let result = near_sdk::borsh::BorshSerialize::try_to_vec(&result) | |
.expect("Failed to serialize the return value using Borsh."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn last_block_number() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.last_block_number(); | |
let result = near_sdk::borsh::BorshSerialize::try_to_vec(&result) | |
.expect("Failed to serialize the return value using Borsh."); | |
near_sdk::env::value_return(&result); | |
} | |
/// Returns the block hash from the canonical chain. | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn block_hash() { | |
near_sdk::env::setup_panic_hook(); | |
struct Input { | |
index: u64, | |
} | |
impl borsh::de::BorshDeserialize for Input | |
where | |
u64: borsh::BorshDeserialize, | |
{ | |
fn deserialize( | |
buf: &mut &[u8], | |
) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | |
Ok(Self { | |
index: borsh::BorshDeserialize::deserialize(buf)?, | |
}) | |
} | |
} | |
let Input { index }: Input = near_sdk::borsh::BorshDeserialize::try_from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from Borsh."); | |
let contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.block_hash(index); | |
let result = near_sdk::borsh::BorshSerialize::try_to_vec(&result) | |
.expect("Failed to serialize the return value using Borsh."); | |
near_sdk::env::value_return(&result); | |
} | |
/// Returns all hashes known for that height. | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn known_hashes() { | |
near_sdk::env::setup_panic_hook(); | |
struct Input { | |
index: u64, | |
} | |
impl borsh::de::BorshDeserialize for Input | |
where | |
u64: borsh::BorshDeserialize, | |
{ | |
fn deserialize( | |
buf: &mut &[u8], | |
) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | |
Ok(Self { | |
index: borsh::BorshDeserialize::deserialize(buf)?, | |
}) | |
} | |
} | |
let Input { index }: Input = near_sdk::borsh::BorshDeserialize::try_from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from Borsh."); | |
let contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.known_hashes(index); | |
let result = near_sdk::borsh::BorshSerialize::try_to_vec(&result) | |
.expect("Failed to serialize the return value using Borsh."); | |
near_sdk::env::value_return(&result); | |
} | |
/// Returns block hash and the number of confirmations. | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn block_hash_safe() { | |
near_sdk::env::setup_panic_hook(); | |
struct Input { | |
index: u64, | |
} | |
impl borsh::de::BorshDeserialize for Input | |
where | |
u64: borsh::BorshDeserialize, | |
{ | |
fn deserialize( | |
buf: &mut &[u8], | |
) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | |
Ok(Self { | |
index: borsh::BorshDeserialize::deserialize(buf)?, | |
}) | |
} | |
} | |
let Input { index }: Input = near_sdk::borsh::BorshDeserialize::try_from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from Borsh."); | |
let contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.block_hash_safe(index); | |
let result = near_sdk::borsh::BorshSerialize::try_to_vec(&result) | |
.expect("Failed to serialize the return value using Borsh."); | |
near_sdk::env::value_return(&result); | |
} | |
/// Add the block header to the client. | |
/// `block_header` -- RLP-encoded Ethereum header; | |
/// `dag_nodes` -- dag nodes with their merkle proofs. | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn add_block_header() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method add_block_header doesn\'t accept deposit"); | |
} | |
struct Input { | |
block_header: Vec<u8>, | |
dag_nodes: Vec<DoubleNodeWithMerkleProof>, | |
} | |
impl borsh::de::BorshDeserialize for Input | |
where | |
Vec<u8>: borsh::BorshDeserialize, | |
Vec<DoubleNodeWithMerkleProof>: borsh::BorshDeserialize, | |
{ | |
fn deserialize( | |
buf: &mut &[u8], | |
) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | |
Ok(Self { | |
block_header: borsh::BorshDeserialize::deserialize(buf)?, | |
dag_nodes: borsh::BorshDeserialize::deserialize(buf)?, | |
}) | |
} | |
} | |
let Input { | |
block_header, | |
dag_nodes, | |
}: Input = near_sdk::borsh::BorshDeserialize::try_from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from Borsh."); | |
let mut contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
contract.add_block_header(block_header, dag_nodes); | |
near_sdk::env::state_write(&contract); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn update_trusted_signer() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method update_trusted_signer doesn\'t accept deposit"); | |
} | |
#[serde(crate = "near_sdk::serde")] | |
struct Input { | |
trusted_signer: Option<AccountId>, | |
} | |
#[doc(hidden)] | |
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] | |
const _IMPL_DESERIALIZE_FOR_Input: () = { | |
use near_sdk::serde as _serde; | |
#[automatically_derived] | |
impl<'de> near_sdk::serde::Deserialize<'de> for Input { | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> near_sdk::serde::export::Result<Self, __D::Error> | |
where | |
__D: near_sdk::serde::Deserializer<'de>, | |
{ | |
#[allow(non_camel_case_types)] | |
enum __Field { | |
__field0, | |
__ignore, | |
} | |
struct __FieldVisitor; | |
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { | |
type Value = __Field; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "field identifier") | |
} | |
fn visit_u64<__E>( | |
self, | |
__value: u64, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
0u64 => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Err(_serde::de::Error::invalid_value( | |
_serde::de::Unexpected::Unsigned(__value), | |
&"field index 0 <= i < 1", | |
)), | |
} | |
} | |
fn visit_str<__E>( | |
self, | |
__value: &str, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
"trusted_signer" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
fn visit_bytes<__E>( | |
self, | |
__value: &[u8], | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
b"trusted_signer" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
} | |
impl<'de> _serde::Deserialize<'de> for __Field { | |
#[inline] | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> _serde::export::Result<Self, __D::Error> | |
where | |
__D: _serde::Deserializer<'de>, | |
{ | |
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) | |
} | |
} | |
struct __Visitor<'de> { | |
marker: _serde::export::PhantomData<Input>, | |
lifetime: _serde::export::PhantomData<&'de ()>, | |
} | |
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { | |
type Value = Input; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "struct Input") | |
} | |
#[inline] | |
fn visit_seq<__A>( | |
self, | |
mut __seq: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::SeqAccess<'de>, | |
{ | |
let __field0 = match match _serde::de::SeqAccess::next_element::< | |
Option<AccountId>, | |
>(&mut __seq) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} { | |
_serde::export::Some(__value) => __value, | |
_serde::export::None => { | |
return _serde::export::Err(_serde::de::Error::invalid_length( | |
0usize, | |
&"struct Input with 1 element", | |
)); | |
} | |
}; | |
_serde::export::Ok(Input { | |
trusted_signer: __field0, | |
}) | |
} | |
#[inline] | |
fn visit_map<__A>( | |
self, | |
mut __map: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::MapAccess<'de>, | |
{ | |
let mut __field0: _serde::export::Option<Option<AccountId>> = | |
_serde::export::None; | |
while let _serde::export::Some(__key) = | |
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
{ | |
match __key { | |
__Field::__field0 => { | |
if _serde::export::Option::is_some(&__field0) { | |
return _serde::export::Err( | |
<__A::Error as _serde::de::Error>::duplicate_field( | |
"trusted_signer", | |
), | |
); | |
} | |
__field0 = _serde::export::Some( | |
match _serde::de::MapAccess::next_value::<Option<AccountId>>( | |
&mut __map, | |
) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
); | |
} | |
_ => { | |
let _ = match _serde::de::MapAccess::next_value::< | |
_serde::de::IgnoredAny, | |
>(&mut __map) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}; | |
} | |
} | |
} | |
let __field0 = match __field0 { | |
_serde::export::Some(__field0) => __field0, | |
_serde::export::None => { | |
match _serde::private::de::missing_field("trusted_signer") { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
} | |
}; | |
_serde::export::Ok(Input { | |
trusted_signer: __field0, | |
}) | |
} | |
} | |
const FIELDS: &'static [&'static str] = &["trusted_signer"]; | |
_serde::Deserializer::deserialize_struct( | |
__deserializer, | |
"Input", | |
FIELDS, | |
__Visitor { | |
marker: _serde::export::PhantomData::<Input>, | |
lifetime: _serde::export::PhantomData, | |
}, | |
) | |
} | |
} | |
}; | |
let Input { trusted_signer }: Input = near_sdk::serde_json::from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from JSON."); | |
let mut contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
contract.update_trusted_signer(trusted_signer); | |
near_sdk::env::state_write(&contract); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn get_trusted_signer() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthClient = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.get_trusted_signer(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
impl EthClient { | |
/// Record the header. If needed update the canonical chain and perform the GC. | |
fn record_header(&mut self, header: BlockHeader) { | |
env::log_str("Record header"); | |
let best_info = self.infos.get(&self.best_header_hash).unwrap(); | |
let header_hash = header.hash.unwrap(); | |
let header_number = header.number; | |
if header_number + self.finalized_gc_threshold < best_info.number { | |
{ | |
::std::rt::begin_panic( | |
"Header is too old to have a chance to appear on the canonical chain.", | |
) | |
}; | |
} | |
let parent_info = self | |
.infos | |
.get(&header.parent_hash) | |
.expect("Header has unknown parent. Parent should be submitted first."); | |
let mut all_hashes = self | |
.all_header_hashes | |
.get(&header_number) | |
.unwrap_or_default(); | |
if !all_hashes.iter().find(|x| **x == header_hash).is_none() { | |
{ | |
::std::rt::panic_fmt(::core::fmt::Arguments::new_v1( | |
&["Header is already known. Number: "], | |
&[::core::fmt::ArgumentV1::new_display(&header_number)], | |
)) | |
} | |
}; | |
all_hashes.push(header_hash); | |
self.all_header_hashes.insert(&header_number, &all_hashes); | |
env::log_str("Inserting header"); | |
self.headers.insert(&header_hash, &header); | |
let info = HeaderInfo { | |
total_difficulty: parent_info.total_difficulty + header.difficulty, | |
parent_hash: header.parent_hash.clone(), | |
number: header_number, | |
}; | |
self.infos.insert(&header_hash, &info); | |
env::log_str("Inserted"); | |
if info.total_difficulty > best_info.total_difficulty | |
|| (info.total_difficulty == best_info.total_difficulty | |
&& header.difficulty % 2 == U256::default()) | |
{ | |
env::log_str("Canonical chain needs to be updated."); | |
if best_info.number > info.number { | |
for number in info.number + 1..=best_info.number { | |
self.canonical_header_hashes.remove(&number); | |
} | |
} | |
self.best_header_hash = header_hash; | |
self.canonical_header_hashes | |
.insert(&header_number, &header_hash); | |
let mut number = header.number - 1; | |
let mut current_hash = info.parent_hash; | |
loop { | |
let prev_value = self.canonical_header_hashes.insert(&number, ¤t_hash); | |
if number == 0 || prev_value == Some(current_hash) { | |
break; | |
} | |
if let Some(info) = self.infos.get(¤t_hash) { | |
current_hash = info.parent_hash; | |
} else { | |
break; | |
} | |
number -= 1; | |
} | |
if header_number >= self.hashes_gc_threshold { | |
self.gc_canonical_chain(header_number - self.hashes_gc_threshold); | |
} | |
if header_number >= self.finalized_gc_threshold { | |
self.gc_headers(header_number - self.finalized_gc_threshold); | |
} | |
} | |
} | |
/// Remove hashes from the canonical chain that are at least as old as the given header number. | |
fn gc_canonical_chain(&mut self, mut header_number: u64) { | |
loop { | |
if self.canonical_header_hashes.get(&header_number).is_some() { | |
self.canonical_header_hashes.remove(&header_number); | |
if header_number == 0 { | |
break; | |
} else { | |
header_number -= 1; | |
} | |
} else { | |
break; | |
} | |
} | |
} | |
/// 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_str( | |
{ | |
let res = ::alloc::fmt::format(::core::fmt::Arguments::new_v1( | |
&["Run headers GC. Used gas: "], | |
&[::core::fmt::ArgumentV1::new_debug(&env::used_gas())], | |
)); | |
res | |
} | |
.as_str(), | |
); | |
loop { | |
if let Some(all_headers) = self.all_header_hashes.get(&header_number) { | |
for hash in all_headers { | |
self.headers.remove_raw(&hash.try_to_vec().unwrap()); | |
self.infos.remove(&hash); | |
} | |
self.all_header_hashes.remove(&header_number); | |
if header_number == 0 { | |
break; | |
} else { | |
header_number -= 1; | |
} | |
} else { | |
break; | |
} | |
} | |
env::log_str( | |
{ | |
let res = ::alloc::fmt::format(::core::fmt::Arguments::new_v1( | |
&["Finish headers GC. Used gas: "], | |
&[::core::fmt::ArgumentV1::new_debug(&env::used_gas())], | |
)); | |
res | |
} | |
.as_str(), | |
); | |
} | |
/// Verify PoW of the header. | |
fn verify_header( | |
&self, | |
header: &BlockHeader, | |
prev: &BlockHeader, | |
dag_nodes: &[DoubleNodeWithMerkleProof], | |
) -> bool { | |
let (_mix_hash, result) = self.hashimoto_merkle( | |
&header.partial_hash.unwrap(), | |
&header.nonce, | |
header.number, | |
dag_nodes, | |
); | |
U256((result.0).0.into()) < U256(ethash::cross_boundary(header.difficulty.0)) | |
&& (!self.validate_ethash | |
|| (header.difficulty < prev.difficulty * 101 / 100 | |
&& header.difficulty > prev.difficulty * 99 / 100)) | |
&& header.gas_used <= header.gas_limit | |
&& header.gas_limit < prev.gas_limit * 1025 / 1024 | |
&& header.gas_limit > prev.gas_limit * 1023 / 1024 | |
&& header.gas_limit >= U256(5000.into()) | |
&& header.timestamp > prev.timestamp | |
&& header.number == prev.number + 1 | |
&& header.parent_hash == prev.hash.unwrap() | |
&& header.extra_data.len() <= 32 | |
} | |
/// Verify merkle paths to the DAG nodes. | |
fn hashimoto_merkle( | |
&self, | |
header_hash: &H256, | |
nonce: &H64, | |
header_number: u64, | |
nodes: &[DoubleNodeWithMerkleProof], | |
) -> (H256, H256) { | |
let index = std::cell::RefCell::new(0); | |
let merkle_root = self.dag_merkle_root((header_number as usize / 30000) as u64); | |
let pair = ethash::hashimoto_with_hasher( | |
header_hash.0, | |
nonce.0, | |
ethash::get_full_size(header_number / 30000), | |
|offset| { | |
let idx = *index.borrow_mut(); | |
*index.borrow_mut() += 1; | |
let node = &nodes[idx / 2]; | |
if idx % 2 == 0 && self.validate_ethash { | |
{ | |
match (&merkle_root, &node.apply_merkle_proof((offset / 2) as u64)) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
let kind = ::core::panicking::AssertKind::Eq; | |
::core::panicking::assert_failed( | |
kind, | |
&*left_val, | |
&*right_val, | |
::core::option::Option::None, | |
); | |
} | |
} | |
} | |
}; | |
}; | |
let mut data = (node.dag_nodes[idx % 2].0).0; | |
data[..32].reverse(); | |
data[32..].reverse(); | |
data.into() | |
}, | |
near_keccak256, | |
near_keccak512, | |
); | |
(H256(pair.0), H256(pair.1)) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(prelude_import)] | |
#[prelude_import] | |
use std::prelude::rust_2018::*; | |
#[macro_use] | |
extern crate std; | |
use borsh::{BorshDeserialize, BorshSerialize}; | |
use eth_types::{near_keccak256, BlockHeader, LogEntry, Receipt, H256}; | |
use near_plugins::{only, pause, FullAccessKeyFallback, Ownable, Pausable, Upgradable}; | |
use near_sdk::{env, ext_contract, near_bindgen, AccountId, Gas, PanicOnDefault, PromiseOrValue}; | |
use rlp::Rlp; | |
/// Gas to call block_hash_safe | |
const BLOCK_HASH_SAFE_GAS: Gas = Gas(10 * Gas::ONE_TERA.0); | |
/// Gas to call on_block_hash | |
const ON_BLOCK_HASH_GAS: Gas = Gas(5 * Gas::ONE_TERA.0); | |
pub struct EthProver { | |
bridge_smart_contract: AccountId, | |
__paused: u128, | |
} | |
impl borsh::de::BorshDeserialize for EthProver | |
where | |
AccountId: borsh::BorshDeserialize, | |
u128: borsh::BorshDeserialize, | |
{ | |
fn deserialize(buf: &mut &[u8]) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | |
Ok(Self { | |
bridge_smart_contract: borsh::BorshDeserialize::deserialize(buf)?, | |
__paused: borsh::BorshDeserialize::deserialize(buf)?, | |
}) | |
} | |
} | |
impl borsh::ser::BorshSerialize for EthProver | |
where | |
AccountId: borsh::ser::BorshSerialize, | |
u128: borsh::ser::BorshSerialize, | |
{ | |
fn serialize<W: borsh::maybestd::io::Write>( | |
&self, | |
writer: &mut W, | |
) -> ::core::result::Result<(), borsh::maybestd::io::Error> { | |
borsh::BorshSerialize::serialize(&self.bridge_smart_contract, writer)?; | |
borsh::BorshSerialize::serialize(&self.__paused, writer)?; | |
Ok(()) | |
} | |
} | |
impl Default for EthProver { | |
fn default() -> Self { | |
near_sdk::env::panic_str("The contract is not initialized"); | |
} | |
} | |
impl Ownable for EthProver { | |
fn owner_storage_key(&self) -> Vec<u8> { | |
("__OWNER__").as_bytes().to_vec() | |
} | |
fn owner_get(&self) -> Option<::near_sdk::AccountId> { | |
::near_sdk::env::storage_read(&self.owner_storage_key()).map(|owner_bytes| { | |
let owner_raw = String::from_utf8(owner_bytes).expect("Ownable: Invalid string format"); | |
std::convert::TryInto::try_into(owner_raw).expect("Ownable: Invalid account id") | |
}) | |
} | |
fn owner_set(&mut self, owner: Option<::near_sdk::AccountId>) { | |
let current_owner = self.owner_get(); | |
if let Some(owner) = current_owner.as_ref() { | |
{ | |
match (&&::near_sdk::env::predecessor_account_id(), &owner) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
let kind = ::core::panicking::AssertKind::Eq; | |
::core::panicking::assert_failed( | |
kind, | |
&*left_val, | |
&*right_val, | |
::core::option::Option::Some(::core::fmt::Arguments::new_v1( | |
&["Ownable: Only owner can update current owner"], | |
&[], | |
)), | |
); | |
} | |
} | |
} | |
}; | |
} else { | |
{ | |
match ( | |
&::near_sdk::env::predecessor_account_id(), | |
&::near_sdk::env::current_account_id(), | |
) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
let kind = ::core::panicking::AssertKind::Eq; | |
::core::panicking::assert_failed( | |
kind, | |
&*left_val, | |
&*right_val, | |
::core::option::Option::Some(::core::fmt::Arguments::new_v1( | |
&["Ownable: Owner not set. Only self can set the owner"], | |
&[], | |
)), | |
); | |
} | |
} | |
} | |
}; | |
} | |
::near_sdk::env::log_str( | |
near_plugins::events::AsEvent::event(&near_plugins::ownable::OwnershipTransferred { | |
previous_owner: current_owner, | |
new_owner: owner.clone(), | |
}) | |
.as_ref(), | |
); | |
match owner.as_ref() { | |
Some(owner) => { | |
::near_sdk::env::storage_write(&self.owner_storage_key(), owner.as_ref().as_bytes()) | |
} | |
None => ::near_sdk::env::storage_remove(&self.owner_storage_key()), | |
}; | |
} | |
fn owner_is(&self) -> bool { | |
self.owner_get().map_or(false, |owner| { | |
owner == ::near_sdk::env::predecessor_account_id() | |
}) | |
} | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn owner_storage_key() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.owner_storage_key(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn owner_get() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.owner_get(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn owner_set() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method owner_set doesn\'t accept deposit"); | |
} | |
#[serde(crate = "near_sdk::serde")] | |
struct Input { | |
owner: Option<::near_sdk::AccountId>, | |
} | |
#[doc(hidden)] | |
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] | |
const _IMPL_DESERIALIZE_FOR_Input: () = { | |
use near_sdk::serde as _serde; | |
#[automatically_derived] | |
impl<'de> near_sdk::serde::Deserialize<'de> for Input { | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> near_sdk::serde::export::Result<Self, __D::Error> | |
where | |
__D: near_sdk::serde::Deserializer<'de>, | |
{ | |
#[allow(non_camel_case_types)] | |
enum __Field { | |
__field0, | |
__ignore, | |
} | |
struct __FieldVisitor; | |
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { | |
type Value = __Field; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "field identifier") | |
} | |
fn visit_u64<__E>( | |
self, | |
__value: u64, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
0u64 => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Err(_serde::de::Error::invalid_value( | |
_serde::de::Unexpected::Unsigned(__value), | |
&"field index 0 <= i < 1", | |
)), | |
} | |
} | |
fn visit_str<__E>( | |
self, | |
__value: &str, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
"owner" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
fn visit_bytes<__E>( | |
self, | |
__value: &[u8], | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
b"owner" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
} | |
impl<'de> _serde::Deserialize<'de> for __Field { | |
#[inline] | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> _serde::export::Result<Self, __D::Error> | |
where | |
__D: _serde::Deserializer<'de>, | |
{ | |
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) | |
} | |
} | |
struct __Visitor<'de> { | |
marker: _serde::export::PhantomData<Input>, | |
lifetime: _serde::export::PhantomData<&'de ()>, | |
} | |
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { | |
type Value = Input; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "struct Input") | |
} | |
#[inline] | |
fn visit_seq<__A>( | |
self, | |
mut __seq: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::SeqAccess<'de>, | |
{ | |
let __field0 = match match _serde::de::SeqAccess::next_element::< | |
Option<::near_sdk::AccountId>, | |
>(&mut __seq) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} { | |
_serde::export::Some(__value) => __value, | |
_serde::export::None => { | |
return _serde::export::Err(_serde::de::Error::invalid_length( | |
0usize, | |
&"struct Input with 1 element", | |
)); | |
} | |
}; | |
_serde::export::Ok(Input { owner: __field0 }) | |
} | |
#[inline] | |
fn visit_map<__A>( | |
self, | |
mut __map: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::MapAccess<'de>, | |
{ | |
let mut __field0: _serde::export::Option<Option<::near_sdk::AccountId>> = | |
_serde::export::None; | |
while let _serde::export::Some(__key) = | |
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
{ | |
match __key { | |
__Field::__field0 => { | |
if _serde::export::Option::is_some(&__field0) { | |
return _serde::export::Err( | |
<__A::Error as _serde::de::Error>::duplicate_field( | |
"owner", | |
), | |
); | |
} | |
__field0 = _serde::export::Some( | |
match _serde::de::MapAccess::next_value::< | |
Option<::near_sdk::AccountId>, | |
>(&mut __map) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
); | |
} | |
_ => { | |
let _ = match _serde::de::MapAccess::next_value::< | |
_serde::de::IgnoredAny, | |
>(&mut __map) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}; | |
} | |
} | |
} | |
let __field0 = match __field0 { | |
_serde::export::Some(__field0) => __field0, | |
_serde::export::None => { | |
match _serde::private::de::missing_field("owner") { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
} | |
}; | |
_serde::export::Ok(Input { owner: __field0 }) | |
} | |
} | |
const FIELDS: &'static [&'static str] = &["owner"]; | |
_serde::Deserializer::deserialize_struct( | |
__deserializer, | |
"Input", | |
FIELDS, | |
__Visitor { | |
marker: _serde::export::PhantomData::<Input>, | |
lifetime: _serde::export::PhantomData, | |
}, | |
) | |
} | |
} | |
}; | |
let Input { owner }: Input = near_sdk::serde_json::from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from JSON."); | |
let mut contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
contract.owner_set(owner); | |
near_sdk::env::state_write(&contract); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn owner_is() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.owner_is(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
impl Pausable for EthProver { | |
fn pa_storage_key(&self) -> Vec<u8> { | |
("__PAUSE__").as_bytes().to_vec() | |
} | |
fn pa_is_paused(&self, key: String) -> bool { | |
self.pa_all_paused() | |
.map(|keys| keys.contains(&key) || keys.contains("ALL")) | |
.unwrap_or(false) | |
} | |
fn pa_all_paused(&self) -> Option<std::collections::HashSet<String>> { | |
::near_sdk::env::storage_read(self.pa_storage_key().as_ref()).map(|value| { | |
std::collections::HashSet::try_from_slice(value.as_ref()) | |
.expect("Pausable: Invalid format for paused keys") | |
}) | |
} | |
fn pa_pause_feature(&mut self, key: String) { | |
if !self.owner_is() { | |
{ | |
::std::rt::begin_panic("Ownable: Method must be called from owner") | |
} | |
}; | |
let mut paused_keys = self.pa_all_paused().unwrap_or_default(); | |
paused_keys.insert(key.clone()); | |
::near_sdk::env::log_str( | |
near_plugins::events::AsEvent::event(&near_plugins::pausable::Pause { | |
by: ::near_sdk::env::predecessor_account_id(), | |
key, | |
}) | |
.as_ref(), | |
); | |
::near_sdk::env::storage_write( | |
self.pa_storage_key().as_ref(), | |
paused_keys | |
.try_to_vec() | |
.expect("Pausable: Unexpected error serializing keys") | |
.as_ref(), | |
); | |
} | |
fn pa_unpause_feature(&mut self, key: String) { | |
if !self.owner_is() { | |
{ | |
::std::rt::begin_panic("Ownable: Method must be called from owner") | |
} | |
}; | |
let mut paused_keys = self.pa_all_paused().unwrap_or_default(); | |
paused_keys.remove(&key); | |
::near_sdk::env::log_str( | |
near_plugins::events::AsEvent::event(&near_plugins::pausable::Unpause { | |
by: ::near_sdk::env::predecessor_account_id(), | |
key, | |
}) | |
.as_ref(), | |
); | |
if paused_keys.is_empty() { | |
::near_sdk::env::storage_remove(self.pa_storage_key().as_ref()); | |
} else { | |
::near_sdk::env::storage_write( | |
self.pa_storage_key().as_ref(), | |
paused_keys | |
.try_to_vec() | |
.expect("Pausable: Unexpected error serializing keys") | |
.as_ref(), | |
); | |
} | |
} | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn pa_storage_key() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.pa_storage_key(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn pa_is_paused() { | |
near_sdk::env::setup_panic_hook(); | |
#[serde(crate = "near_sdk::serde")] | |
struct Input { | |
key: String, | |
} | |
#[doc(hidden)] | |
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] | |
const _IMPL_DESERIALIZE_FOR_Input: () = { | |
use near_sdk::serde as _serde; | |
#[automatically_derived] | |
impl<'de> near_sdk::serde::Deserialize<'de> for Input { | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> near_sdk::serde::export::Result<Self, __D::Error> | |
where | |
__D: near_sdk::serde::Deserializer<'de>, | |
{ | |
#[allow(non_camel_case_types)] | |
enum __Field { | |
__field0, | |
__ignore, | |
} | |
struct __FieldVisitor; | |
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { | |
type Value = __Field; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "field identifier") | |
} | |
fn visit_u64<__E>( | |
self, | |
__value: u64, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
0u64 => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Err(_serde::de::Error::invalid_value( | |
_serde::de::Unexpected::Unsigned(__value), | |
&"field index 0 <= i < 1", | |
)), | |
} | |
} | |
fn visit_str<__E>( | |
self, | |
__value: &str, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
"key" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
fn visit_bytes<__E>( | |
self, | |
__value: &[u8], | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
b"key" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
} | |
impl<'de> _serde::Deserialize<'de> for __Field { | |
#[inline] | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> _serde::export::Result<Self, __D::Error> | |
where | |
__D: _serde::Deserializer<'de>, | |
{ | |
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) | |
} | |
} | |
struct __Visitor<'de> { | |
marker: _serde::export::PhantomData<Input>, | |
lifetime: _serde::export::PhantomData<&'de ()>, | |
} | |
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { | |
type Value = Input; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "struct Input") | |
} | |
#[inline] | |
fn visit_seq<__A>( | |
self, | |
mut __seq: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::SeqAccess<'de>, | |
{ | |
let __field0 = | |
match match _serde::de::SeqAccess::next_element::<String>(&mut __seq) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} { | |
_serde::export::Some(__value) => __value, | |
_serde::export::None => { | |
return _serde::export::Err(_serde::de::Error::invalid_length( | |
0usize, | |
&"struct Input with 1 element", | |
)); | |
} | |
}; | |
_serde::export::Ok(Input { key: __field0 }) | |
} | |
#[inline] | |
fn visit_map<__A>( | |
self, | |
mut __map: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::MapAccess<'de>, | |
{ | |
let mut __field0: _serde::export::Option<String> = _serde::export::None; | |
while let _serde::export::Some(__key) = | |
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
{ | |
match __key { | |
__Field::__field0 => { | |
if _serde::export::Option::is_some(&__field0) { | |
return _serde::export::Err( | |
<__A::Error as _serde::de::Error>::duplicate_field( | |
"key", | |
), | |
); | |
} | |
__field0 = _serde::export::Some( | |
match _serde::de::MapAccess::next_value::<String>( | |
&mut __map, | |
) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
); | |
} | |
_ => { | |
let _ = match _serde::de::MapAccess::next_value::< | |
_serde::de::IgnoredAny, | |
>(&mut __map) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}; | |
} | |
} | |
} | |
let __field0 = match __field0 { | |
_serde::export::Some(__field0) => __field0, | |
_serde::export::None => match _serde::private::de::missing_field("key") | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
}; | |
_serde::export::Ok(Input { key: __field0 }) | |
} | |
} | |
const FIELDS: &'static [&'static str] = &["key"]; | |
_serde::Deserializer::deserialize_struct( | |
__deserializer, | |
"Input", | |
FIELDS, | |
__Visitor { | |
marker: _serde::export::PhantomData::<Input>, | |
lifetime: _serde::export::PhantomData, | |
}, | |
) | |
} | |
} | |
}; | |
let Input { key }: Input = near_sdk::serde_json::from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from JSON."); | |
let contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.pa_is_paused(key); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn pa_all_paused() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.pa_all_paused(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn pa_pause_feature() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method pa_pause_feature doesn\'t accept deposit"); | |
} | |
#[serde(crate = "near_sdk::serde")] | |
struct Input { | |
key: String, | |
} | |
#[doc(hidden)] | |
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] | |
const _IMPL_DESERIALIZE_FOR_Input: () = { | |
use near_sdk::serde as _serde; | |
#[automatically_derived] | |
impl<'de> near_sdk::serde::Deserialize<'de> for Input { | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> near_sdk::serde::export::Result<Self, __D::Error> | |
where | |
__D: near_sdk::serde::Deserializer<'de>, | |
{ | |
#[allow(non_camel_case_types)] | |
enum __Field { | |
__field0, | |
__ignore, | |
} | |
struct __FieldVisitor; | |
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { | |
type Value = __Field; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "field identifier") | |
} | |
fn visit_u64<__E>( | |
self, | |
__value: u64, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
0u64 => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Err(_serde::de::Error::invalid_value( | |
_serde::de::Unexpected::Unsigned(__value), | |
&"field index 0 <= i < 1", | |
)), | |
} | |
} | |
fn visit_str<__E>( | |
self, | |
__value: &str, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
"key" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
fn visit_bytes<__E>( | |
self, | |
__value: &[u8], | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
b"key" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
} | |
impl<'de> _serde::Deserialize<'de> for __Field { | |
#[inline] | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> _serde::export::Result<Self, __D::Error> | |
where | |
__D: _serde::Deserializer<'de>, | |
{ | |
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) | |
} | |
} | |
struct __Visitor<'de> { | |
marker: _serde::export::PhantomData<Input>, | |
lifetime: _serde::export::PhantomData<&'de ()>, | |
} | |
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { | |
type Value = Input; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "struct Input") | |
} | |
#[inline] | |
fn visit_seq<__A>( | |
self, | |
mut __seq: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::SeqAccess<'de>, | |
{ | |
let __field0 = | |
match match _serde::de::SeqAccess::next_element::<String>(&mut __seq) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} { | |
_serde::export::Some(__value) => __value, | |
_serde::export::None => { | |
return _serde::export::Err(_serde::de::Error::invalid_length( | |
0usize, | |
&"struct Input with 1 element", | |
)); | |
} | |
}; | |
_serde::export::Ok(Input { key: __field0 }) | |
} | |
#[inline] | |
fn visit_map<__A>( | |
self, | |
mut __map: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::MapAccess<'de>, | |
{ | |
let mut __field0: _serde::export::Option<String> = _serde::export::None; | |
while let _serde::export::Some(__key) = | |
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
{ | |
match __key { | |
__Field::__field0 => { | |
if _serde::export::Option::is_some(&__field0) { | |
return _serde::export::Err( | |
<__A::Error as _serde::de::Error>::duplicate_field( | |
"key", | |
), | |
); | |
} | |
__field0 = _serde::export::Some( | |
match _serde::de::MapAccess::next_value::<String>( | |
&mut __map, | |
) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
); | |
} | |
_ => { | |
let _ = match _serde::de::MapAccess::next_value::< | |
_serde::de::IgnoredAny, | |
>(&mut __map) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}; | |
} | |
} | |
} | |
let __field0 = match __field0 { | |
_serde::export::Some(__field0) => __field0, | |
_serde::export::None => match _serde::private::de::missing_field("key") | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
}; | |
_serde::export::Ok(Input { key: __field0 }) | |
} | |
} | |
const FIELDS: &'static [&'static str] = &["key"]; | |
_serde::Deserializer::deserialize_struct( | |
__deserializer, | |
"Input", | |
FIELDS, | |
__Visitor { | |
marker: _serde::export::PhantomData::<Input>, | |
lifetime: _serde::export::PhantomData, | |
}, | |
) | |
} | |
} | |
}; | |
let Input { key }: Input = near_sdk::serde_json::from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from JSON."); | |
let mut contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
contract.pa_pause_feature(key); | |
near_sdk::env::state_write(&contract); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn pa_unpause_feature() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method pa_unpause_feature doesn\'t accept deposit"); | |
} | |
#[serde(crate = "near_sdk::serde")] | |
struct Input { | |
key: String, | |
} | |
#[doc(hidden)] | |
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] | |
const _IMPL_DESERIALIZE_FOR_Input: () = { | |
use near_sdk::serde as _serde; | |
#[automatically_derived] | |
impl<'de> near_sdk::serde::Deserialize<'de> for Input { | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> near_sdk::serde::export::Result<Self, __D::Error> | |
where | |
__D: near_sdk::serde::Deserializer<'de>, | |
{ | |
#[allow(non_camel_case_types)] | |
enum __Field { | |
__field0, | |
__ignore, | |
} | |
struct __FieldVisitor; | |
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { | |
type Value = __Field; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "field identifier") | |
} | |
fn visit_u64<__E>( | |
self, | |
__value: u64, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
0u64 => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Err(_serde::de::Error::invalid_value( | |
_serde::de::Unexpected::Unsigned(__value), | |
&"field index 0 <= i < 1", | |
)), | |
} | |
} | |
fn visit_str<__E>( | |
self, | |
__value: &str, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
"key" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
fn visit_bytes<__E>( | |
self, | |
__value: &[u8], | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
b"key" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
} | |
impl<'de> _serde::Deserialize<'de> for __Field { | |
#[inline] | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> _serde::export::Result<Self, __D::Error> | |
where | |
__D: _serde::Deserializer<'de>, | |
{ | |
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) | |
} | |
} | |
struct __Visitor<'de> { | |
marker: _serde::export::PhantomData<Input>, | |
lifetime: _serde::export::PhantomData<&'de ()>, | |
} | |
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { | |
type Value = Input; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "struct Input") | |
} | |
#[inline] | |
fn visit_seq<__A>( | |
self, | |
mut __seq: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::SeqAccess<'de>, | |
{ | |
let __field0 = | |
match match _serde::de::SeqAccess::next_element::<String>(&mut __seq) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} { | |
_serde::export::Some(__value) => __value, | |
_serde::export::None => { | |
return _serde::export::Err(_serde::de::Error::invalid_length( | |
0usize, | |
&"struct Input with 1 element", | |
)); | |
} | |
}; | |
_serde::export::Ok(Input { key: __field0 }) | |
} | |
#[inline] | |
fn visit_map<__A>( | |
self, | |
mut __map: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::MapAccess<'de>, | |
{ | |
let mut __field0: _serde::export::Option<String> = _serde::export::None; | |
while let _serde::export::Some(__key) = | |
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
{ | |
match __key { | |
__Field::__field0 => { | |
if _serde::export::Option::is_some(&__field0) { | |
return _serde::export::Err( | |
<__A::Error as _serde::de::Error>::duplicate_field( | |
"key", | |
), | |
); | |
} | |
__field0 = _serde::export::Some( | |
match _serde::de::MapAccess::next_value::<String>( | |
&mut __map, | |
) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
); | |
} | |
_ => { | |
let _ = match _serde::de::MapAccess::next_value::< | |
_serde::de::IgnoredAny, | |
>(&mut __map) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}; | |
} | |
} | |
} | |
let __field0 = match __field0 { | |
_serde::export::Some(__field0) => __field0, | |
_serde::export::None => match _serde::private::de::missing_field("key") | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
}; | |
_serde::export::Ok(Input { key: __field0 }) | |
} | |
} | |
const FIELDS: &'static [&'static str] = &["key"]; | |
_serde::Deserializer::deserialize_struct( | |
__deserializer, | |
"Input", | |
FIELDS, | |
__Visitor { | |
marker: _serde::export::PhantomData::<Input>, | |
lifetime: _serde::export::PhantomData, | |
}, | |
) | |
} | |
} | |
}; | |
let Input { key }: Input = near_sdk::serde_json::from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from JSON."); | |
let mut contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
contract.pa_unpause_feature(key); | |
near_sdk::env::state_write(&contract); | |
} | |
impl Upgradable for EthProver { | |
fn up_storage_key(&self) -> Vec<u8> { | |
("__CODE__").as_bytes().to_vec() | |
} | |
fn up_stage_code(&mut self, code: Vec<u8>) { | |
if !self.owner_is() { | |
{ | |
::std::rt::begin_panic("Ownable: Method must be called from owner") | |
} | |
}; | |
if code.is_empty() { | |
near_sdk::env::storage_remove(self.up_storage_key().as_ref()); | |
} else { | |
near_sdk::env::storage_write(self.up_storage_key().as_ref(), code.as_ref()); | |
} | |
} | |
fn up_staged_code(&self) -> Option<Vec<u8>> { | |
near_sdk::env::storage_read(self.up_storage_key().as_ref()) | |
} | |
fn up_staged_code_hash(&self) -> Option<::near_sdk::CryptoHash> { | |
self.up_staged_code().map(|code| { | |
std::convert::TryInto::try_into(near_sdk::env::sha256(code.as_ref())).unwrap() | |
}) | |
} | |
fn up_deploy_code(&mut self) -> near_sdk::Promise { | |
if !self.owner_is() { | |
{ | |
::std::rt::begin_panic("Ownable: Method must be called from owner") | |
} | |
}; | |
near_sdk::Promise::new(near_sdk::env::current_account_id()) | |
.deploy_contract(self.up_staged_code().expect("Upgradable: No staged code")) | |
} | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn up_storage_key() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.up_storage_key(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn up_stage_code() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method up_stage_code doesn\'t accept deposit"); | |
} | |
struct Input { | |
code: Vec<u8>, | |
} | |
impl borsh::de::BorshDeserialize for Input | |
where | |
Vec<u8>: borsh::BorshDeserialize, | |
{ | |
fn deserialize( | |
buf: &mut &[u8], | |
) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | |
Ok(Self { | |
code: borsh::BorshDeserialize::deserialize(buf)?, | |
}) | |
} | |
} | |
let Input { code }: Input = near_sdk::borsh::BorshDeserialize::try_from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from Borsh."); | |
let mut contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
contract.up_stage_code(code); | |
near_sdk::env::state_write(&contract); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn up_staged_code() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.up_staged_code(); | |
let result = near_sdk::borsh::BorshSerialize::try_to_vec(&result) | |
.expect("Failed to serialize the return value using Borsh."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn up_staged_code_hash() { | |
near_sdk::env::setup_panic_hook(); | |
let contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.up_staged_code_hash(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn up_deploy_code() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method up_deploy_code doesn\'t accept deposit"); | |
} | |
let mut contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.up_deploy_code(); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
near_sdk::env::state_write(&contract); | |
} | |
impl FullAccessKeyFallback for EthProver { | |
fn attach_full_access_key(&mut self, public_key: ::near_sdk::PublicKey) -> near_sdk::Promise { | |
if !self.owner_is() { | |
{ | |
::std::rt::begin_panic("Ownable: Method must be called from owner") | |
} | |
}; | |
let current_account_id = ::near_sdk::env::current_account_id(); | |
::near_sdk::env::log_str( | |
near_plugins::events::AsEvent::event( | |
&near_plugins::full_access_key_fallback::FullAccessKeyAdded { | |
by: current_account_id.clone(), | |
public_key: public_key.clone(), | |
}, | |
) | |
.as_ref(), | |
); | |
::near_sdk::Promise::new(current_account_id).add_full_access_key(public_key) | |
} | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn attach_full_access_key() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method attach_full_access_key doesn\'t accept deposit"); | |
} | |
#[serde(crate = "near_sdk::serde")] | |
struct Input { | |
public_key: ::near_sdk::PublicKey, | |
} | |
#[doc(hidden)] | |
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] | |
const _IMPL_DESERIALIZE_FOR_Input: () = { | |
use near_sdk::serde as _serde; | |
#[automatically_derived] | |
impl<'de> near_sdk::serde::Deserialize<'de> for Input { | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> near_sdk::serde::export::Result<Self, __D::Error> | |
where | |
__D: near_sdk::serde::Deserializer<'de>, | |
{ | |
#[allow(non_camel_case_types)] | |
enum __Field { | |
__field0, | |
__ignore, | |
} | |
struct __FieldVisitor; | |
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { | |
type Value = __Field; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "field identifier") | |
} | |
fn visit_u64<__E>( | |
self, | |
__value: u64, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
0u64 => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Err(_serde::de::Error::invalid_value( | |
_serde::de::Unexpected::Unsigned(__value), | |
&"field index 0 <= i < 1", | |
)), | |
} | |
} | |
fn visit_str<__E>( | |
self, | |
__value: &str, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
"public_key" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
fn visit_bytes<__E>( | |
self, | |
__value: &[u8], | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
b"public_key" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
} | |
impl<'de> _serde::Deserialize<'de> for __Field { | |
#[inline] | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> _serde::export::Result<Self, __D::Error> | |
where | |
__D: _serde::Deserializer<'de>, | |
{ | |
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) | |
} | |
} | |
struct __Visitor<'de> { | |
marker: _serde::export::PhantomData<Input>, | |
lifetime: _serde::export::PhantomData<&'de ()>, | |
} | |
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { | |
type Value = Input; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "struct Input") | |
} | |
#[inline] | |
fn visit_seq<__A>( | |
self, | |
mut __seq: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::SeqAccess<'de>, | |
{ | |
let __field0 = match match _serde::de::SeqAccess::next_element::< | |
::near_sdk::PublicKey, | |
>(&mut __seq) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} { | |
_serde::export::Some(__value) => __value, | |
_serde::export::None => { | |
return _serde::export::Err(_serde::de::Error::invalid_length( | |
0usize, | |
&"struct Input with 1 element", | |
)); | |
} | |
}; | |
_serde::export::Ok(Input { | |
public_key: __field0, | |
}) | |
} | |
#[inline] | |
fn visit_map<__A>( | |
self, | |
mut __map: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::MapAccess<'de>, | |
{ | |
let mut __field0: _serde::export::Option<::near_sdk::PublicKey> = | |
_serde::export::None; | |
while let _serde::export::Some(__key) = | |
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
{ | |
match __key { | |
__Field::__field0 => { | |
if _serde::export::Option::is_some(&__field0) { | |
return _serde::export::Err( | |
<__A::Error as _serde::de::Error>::duplicate_field( | |
"public_key", | |
), | |
); | |
} | |
__field0 = _serde::export::Some( | |
match _serde::de::MapAccess::next_value::< | |
::near_sdk::PublicKey, | |
>(&mut __map) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
); | |
} | |
_ => { | |
let _ = match _serde::de::MapAccess::next_value::< | |
_serde::de::IgnoredAny, | |
>(&mut __map) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}; | |
} | |
} | |
} | |
let __field0 = match __field0 { | |
_serde::export::Some(__field0) => __field0, | |
_serde::export::None => { | |
match _serde::private::de::missing_field("public_key") { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
} | |
}; | |
_serde::export::Ok(Input { | |
public_key: __field0, | |
}) | |
} | |
} | |
const FIELDS: &'static [&'static str] = &["public_key"]; | |
_serde::Deserializer::deserialize_struct( | |
__deserializer, | |
"Input", | |
FIELDS, | |
__Visitor { | |
marker: _serde::export::PhantomData::<Input>, | |
lifetime: _serde::export::PhantomData, | |
}, | |
) | |
} | |
} | |
}; | |
let Input { public_key }: Input = near_sdk::serde_json::from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from JSON."); | |
let mut contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.attach_full_access_key(public_key); | |
let result = near_sdk::serde_json::to_vec(&result) | |
.expect("Failed to serialize the return value using JSON."); | |
near_sdk::env::value_return(&result); | |
near_sdk::env::state_write(&contract); | |
} | |
pub mod remote_self { | |
use super::*; | |
use near_sdk::{Gas, Balance, AccountId, Promise}; | |
pub fn on_block_hash( | |
expected_block_hash: H256, | |
__account_id: AccountId, | |
__balance: near_sdk::Balance, | |
__gas: near_sdk::Gas, | |
) -> near_sdk::Promise { | |
struct Input { | |
expected_block_hash: H256, | |
} | |
impl borsh::ser::BorshSerialize for Input | |
where | |
H256: borsh::ser::BorshSerialize, | |
{ | |
fn serialize<W: borsh::maybestd::io::Write>( | |
&self, | |
writer: &mut W, | |
) -> ::core::result::Result<(), borsh::maybestd::io::Error> { | |
borsh::BorshSerialize::serialize(&self.expected_block_hash, writer)?; | |
Ok(()) | |
} | |
} | |
let args = Input { | |
expected_block_hash, | |
}; | |
let args = near_sdk::borsh::BorshSerialize::try_to_vec(&args) | |
.expect("Failed to serialize the cross contract args using Borsh."); | |
near_sdk::Promise::new(__account_id).function_call( | |
"on_block_hash".to_string(), | |
args, | |
__balance, | |
__gas, | |
) | |
} | |
} | |
pub mod eth_client { | |
use super::*; | |
use near_sdk::{Gas, Balance, AccountId, Promise}; | |
pub fn block_hash_safe( | |
index: u64, | |
__account_id: AccountId, | |
__balance: near_sdk::Balance, | |
__gas: near_sdk::Gas, | |
) -> near_sdk::Promise { | |
struct Input { | |
index: u64, | |
} | |
impl borsh::ser::BorshSerialize for Input | |
where | |
u64: borsh::ser::BorshSerialize, | |
{ | |
fn serialize<W: borsh::maybestd::io::Write>( | |
&self, | |
writer: &mut W, | |
) -> ::core::result::Result<(), borsh::maybestd::io::Error> { | |
borsh::BorshSerialize::serialize(&self.index, writer)?; | |
Ok(()) | |
} | |
} | |
let args = Input { index }; | |
let args = near_sdk::borsh::BorshSerialize::try_to_vec(&args) | |
.expect("Failed to serialize the cross contract args using Borsh."); | |
near_sdk::Promise::new(__account_id).function_call( | |
"block_hash_safe".to_string(), | |
args, | |
__balance, | |
__gas, | |
) | |
} | |
} | |
/// Get element at position `pos` from rlp encoded data, | |
/// and decode it as vector of bytes | |
fn get_vec(data: &Rlp, pos: usize) -> Vec<u8> { | |
data.at(pos).unwrap().as_val::<Vec<u8>>().unwrap() | |
} | |
impl EthProver { | |
pub fn init(bridge_smart_contract: AccountId) -> Self { | |
if !env::state_read::<EthProver>().is_none() { | |
{ | |
::std::rt::begin_panic("The contract is already initialized") | |
} | |
}; | |
Self { | |
bridge_smart_contract, | |
__paused: Default::default(), | |
} | |
} | |
/// Implementation of the callback when the EthClient returns data. | |
/// This method can only be called by the EthProver contract itself (e.g. as callback). | |
/// - `block_hash` is the actual data from the EthClient call | |
/// - `expected_block_hash` is the block hash that we expect to be passed by us. | |
pub fn on_block_hash(&self, block_hash: Option<H256>, expected_block_hash: H256) -> bool { | |
::near_sdk::assert_self(); | |
return block_hash == Some(expected_block_hash); | |
} | |
/// Externally visible method to verify that the given block hash is part of the safe canonical | |
/// chain on the remote EthClient contract. | |
/// Returns a promise. | |
pub fn assert_ethclient_hash( | |
&self, | |
block_number: u64, | |
expected_block_hash: H256, | |
) -> PromiseOrValue<bool> { | |
eth_client::block_hash_safe( | |
block_number, | |
self.bridge_smart_contract.clone(), | |
0, | |
BLOCK_HASH_SAFE_GAS, | |
) | |
.then(remote_self::on_block_hash( | |
expected_block_hash, | |
env::current_account_id(), | |
0, | |
ON_BLOCK_HASH_GAS, | |
)) | |
.into() | |
} | |
pub fn verify_log_entry( | |
&self, | |
log_index: u64, | |
log_entry_data: Vec<u8>, | |
receipt_index: u64, | |
receipt_data: Vec<u8>, | |
header_data: Vec<u8>, | |
proof: Vec<Vec<u8>>, | |
skip_bridge_call: bool, | |
) -> PromiseOrValue<bool> { | |
let mut check_paused = true; | |
if check_paused { | |
if !!self.pa_is_paused("verify_log_entry".to_string()) { | |
{ | |
::std::rt::begin_panic("Pausable: Method is paused") | |
} | |
}; | |
} | |
let log_entry: LogEntry = rlp::decode(log_entry_data.as_slice()).unwrap(); | |
let receipt: Receipt = rlp::decode(receipt_data.as_slice()).unwrap(); | |
let header: BlockHeader = rlp::decode(header_data.as_slice()).unwrap(); | |
{ | |
match (&receipt.logs[log_index as usize], &log_entry) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
let kind = ::core::panicking::AssertKind::Eq; | |
::core::panicking::assert_failed( | |
kind, | |
&*left_val, | |
&*right_val, | |
::core::option::Option::None, | |
); | |
} | |
} | |
} | |
}; | |
let data = | |
Self::verify_trie_proof(header.receipts_root, rlp::encode(&receipt_index), proof); | |
let verification_result = receipt_data == data; | |
if verification_result && skip_bridge_call { | |
return PromiseOrValue::Value(true); | |
} else if !verification_result { | |
return PromiseOrValue::Value(false); | |
} | |
eth_client::block_hash_safe( | |
header.number, | |
self.bridge_smart_contract.clone(), | |
0, | |
BLOCK_HASH_SAFE_GAS, | |
) | |
.then(remote_self::on_block_hash( | |
header.hash.unwrap(), | |
env::current_account_id(), | |
0, | |
ON_BLOCK_HASH_GAS, | |
)) | |
.into() | |
} | |
/// Verify the proof recursively traversing through the key. | |
/// Return the value at the end of the key, in case the proof is valid. | |
/// | |
/// @param expected_root is the expected root of the current node. | |
/// @param key is the key for which we are proving the value. | |
/// @param proof contains relevant information to verify data is valid | |
/// | |
/// Patricia Trie: https://eth.wiki/en/fundamentals/patricia-tree | |
/// Patricia Img: https://ethereum.stackexchange.com/questions/268/ethereum-block-architecture/6413#6413 | |
/// | |
/// Verification: https://github.com/slockit/in3/wiki/Ethereum-Verification-and-MerkleProof#receipt-proof | |
/// Article: https://medium.com/@ouvrard.pierre.alain/merkle-proof-verification-for-ethereum-patricia-tree-48f29658eec | |
/// Python impl: https://gist.github.com/mfornet/0ff283274c0162f1cca45966bccf69ee | |
/// | |
fn verify_trie_proof(expected_root: H256, key: Vec<u8>, proof: Vec<Vec<u8>>) -> Vec<u8> { | |
let mut actual_key = ::alloc::vec::Vec::new(); | |
for el in key { | |
actual_key.push(el / 16); | |
actual_key.push(el % 16); | |
} | |
Self::_verify_trie_proof((expected_root.0).0.into(), &actual_key, &proof, 0, 0) | |
} | |
fn _verify_trie_proof( | |
expected_root: Vec<u8>, | |
key: &Vec<u8>, | |
proof: &Vec<Vec<u8>>, | |
key_index: usize, | |
proof_index: usize, | |
) -> Vec<u8> { | |
let node = &proof[proof_index]; | |
if key_index == 0 { | |
{ | |
match (&near_keccak256(node), &expected_root.as_slice()) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
let kind = ::core::panicking::AssertKind::Eq; | |
::core::panicking::assert_failed( | |
kind, | |
&*left_val, | |
&*right_val, | |
::core::option::Option::None, | |
); | |
} | |
} | |
} | |
}; | |
} else if node.len() < 32 { | |
{ | |
match (&node.as_slice(), &expected_root) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
let kind = ::core::panicking::AssertKind::Eq; | |
::core::panicking::assert_failed( | |
kind, | |
&*left_val, | |
&*right_val, | |
::core::option::Option::None, | |
); | |
} | |
} | |
} | |
}; | |
} else { | |
{ | |
match (&near_keccak256(node), &expected_root.as_slice()) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
let kind = ::core::panicking::AssertKind::Eq; | |
::core::panicking::assert_failed( | |
kind, | |
&*left_val, | |
&*right_val, | |
::core::option::Option::None, | |
); | |
} | |
} | |
} | |
}; | |
} | |
let node = Rlp::new(&node.as_slice()); | |
if node.iter().count() == 17 { | |
if key_index == key.len() { | |
{ | |
match (&(proof_index + 1), &proof.len()) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
let kind = ::core::panicking::AssertKind::Eq; | |
::core::panicking::assert_failed( | |
kind, | |
&*left_val, | |
&*right_val, | |
::core::option::Option::None, | |
); | |
} | |
} | |
} | |
}; | |
get_vec(&node, 16) | |
} else { | |
let new_expected_root = get_vec(&node, key[key_index] as usize); | |
Self::_verify_trie_proof( | |
new_expected_root, | |
key, | |
proof, | |
key_index + 1, | |
proof_index + 1, | |
) | |
} | |
} else { | |
{ | |
match (&node.iter().count(), &2) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
let kind = ::core::panicking::AssertKind::Eq; | |
::core::panicking::assert_failed( | |
kind, | |
&*left_val, | |
&*right_val, | |
::core::option::Option::None, | |
); | |
} | |
} | |
} | |
}; | |
let path_u8 = get_vec(&node, 0); | |
let head = path_u8[0] / 16; | |
if !(head <= 3) { | |
::core::panicking::panic("assertion failed: head <= 3") | |
}; | |
let mut path = ::alloc::vec::Vec::new(); | |
if head % 2 == 1 { | |
path.push(path_u8[0] % 16); | |
} | |
for val in path_u8.into_iter().skip(1) { | |
path.push(val / 16); | |
path.push(val % 16); | |
} | |
{ | |
match (&path.as_slice(), &&key[key_index..key_index + path.len()]) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
let kind = ::core::panicking::AssertKind::Eq; | |
::core::panicking::assert_failed( | |
kind, | |
&*left_val, | |
&*right_val, | |
::core::option::Option::None, | |
); | |
} | |
} | |
} | |
}; | |
if head >= 2 { | |
{ | |
match (&(proof_index + 1), &proof.len()) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
let kind = ::core::panicking::AssertKind::Eq; | |
::core::panicking::assert_failed( | |
kind, | |
&*left_val, | |
&*right_val, | |
::core::option::Option::None, | |
); | |
} | |
} | |
} | |
}; | |
{ | |
match (&(key_index + path.len()), &key.len()) { | |
(left_val, right_val) => { | |
if !(*left_val == *right_val) { | |
let kind = ::core::panicking::AssertKind::Eq; | |
::core::panicking::assert_failed( | |
kind, | |
&*left_val, | |
&*right_val, | |
::core::option::Option::None, | |
); | |
} | |
} | |
} | |
}; | |
get_vec(&node, 1) | |
} else { | |
let new_expected_root = get_vec(&node, 1); | |
Self::_verify_trie_proof( | |
new_expected_root, | |
key, | |
proof, | |
key_index + path.len(), | |
proof_index + 1, | |
) | |
} | |
} | |
} | |
pub fn set_bridge(&mut self, bridge: AccountId) { | |
if !self.owner_is() { | |
{ | |
::std::rt::begin_panic("Ownable: Method must be called from owner") | |
} | |
}; | |
env::log_str( | |
{ | |
let res = ::alloc::fmt::format(::core::fmt::Arguments::new_v1( | |
&["Old bridge account: ", " New bridge account "], | |
&[ | |
::core::fmt::ArgumentV1::new_display(&self.bridge_smart_contract), | |
::core::fmt::ArgumentV1::new_display(&bridge), | |
], | |
)); | |
res | |
} | |
.as_str(), | |
); | |
self.bridge_smart_contract = bridge; | |
} | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn init() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method init doesn\'t accept deposit"); | |
} | |
struct Input { | |
bridge_smart_contract: AccountId, | |
} | |
impl borsh::de::BorshDeserialize for Input | |
where | |
AccountId: borsh::BorshDeserialize, | |
{ | |
fn deserialize( | |
buf: &mut &[u8], | |
) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | |
Ok(Self { | |
bridge_smart_contract: borsh::BorshDeserialize::deserialize(buf)?, | |
}) | |
} | |
} | |
let Input { | |
bridge_smart_contract, | |
}: Input = near_sdk::borsh::BorshDeserialize::try_from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from Borsh."); | |
if near_sdk::env::state_exists() { | |
near_sdk::env::panic_str("The contract has already been initialized"); | |
} | |
let contract = EthProver::init(bridge_smart_contract); | |
near_sdk::env::state_write(&contract); | |
} | |
/// Implementation of the callback when the EthClient returns data. | |
/// This method can only be called by the EthProver contract itself (e.g. as callback). | |
/// - `block_hash` is the actual data from the EthClient call | |
/// - `expected_block_hash` is the block hash that we expect to be passed by us. | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn on_block_hash() { | |
near_sdk::env::setup_panic_hook(); | |
struct Input { | |
expected_block_hash: H256, | |
} | |
impl borsh::de::BorshDeserialize for Input | |
where | |
H256: borsh::BorshDeserialize, | |
{ | |
fn deserialize( | |
buf: &mut &[u8], | |
) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | |
Ok(Self { | |
expected_block_hash: borsh::BorshDeserialize::deserialize(buf)?, | |
}) | |
} | |
} | |
let Input { | |
expected_block_hash, | |
}: Input = near_sdk::borsh::BorshDeserialize::try_from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from Borsh."); | |
let data: Vec<u8> = match near_sdk::env::promise_result(0u64) { | |
near_sdk::PromiseResult::Successful(x) => x, | |
_ => near_sdk::env::panic_str("Callback computation 0 was not successful"), | |
}; | |
let block_hash: Option<H256> = near_sdk::borsh::BorshDeserialize::try_from_slice(&data) | |
.expect("Failed to deserialize callback using Borsh"); | |
let contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.on_block_hash(block_hash, expected_block_hash); | |
let result = near_sdk::borsh::BorshSerialize::try_to_vec(&result) | |
.expect("Failed to serialize the return value using Borsh."); | |
near_sdk::env::value_return(&result); | |
} | |
/// Externally visible method to verify that the given block hash is part of the safe canonical | |
/// chain on the remote EthClient contract. | |
/// Returns a promise. | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn assert_ethclient_hash() { | |
near_sdk::env::setup_panic_hook(); | |
struct Input { | |
block_number: u64, | |
expected_block_hash: H256, | |
} | |
impl borsh::de::BorshDeserialize for Input | |
where | |
u64: borsh::BorshDeserialize, | |
H256: borsh::BorshDeserialize, | |
{ | |
fn deserialize( | |
buf: &mut &[u8], | |
) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | |
Ok(Self { | |
block_number: borsh::BorshDeserialize::deserialize(buf)?, | |
expected_block_hash: borsh::BorshDeserialize::deserialize(buf)?, | |
}) | |
} | |
} | |
let Input { | |
block_number, | |
expected_block_hash, | |
}: Input = near_sdk::borsh::BorshDeserialize::try_from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from Borsh."); | |
let contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.assert_ethclient_hash(block_number, expected_block_hash); | |
let result = near_sdk::borsh::BorshSerialize::try_to_vec(&result) | |
.expect("Failed to serialize the return value using Borsh."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn verify_log_entry() { | |
near_sdk::env::setup_panic_hook(); | |
struct Input { | |
log_index: u64, | |
log_entry_data: Vec<u8>, | |
receipt_index: u64, | |
receipt_data: Vec<u8>, | |
header_data: Vec<u8>, | |
proof: Vec<Vec<u8>>, | |
skip_bridge_call: bool, | |
} | |
impl borsh::de::BorshDeserialize for Input | |
where | |
u64: borsh::BorshDeserialize, | |
Vec<u8>: borsh::BorshDeserialize, | |
u64: borsh::BorshDeserialize, | |
Vec<u8>: borsh::BorshDeserialize, | |
Vec<u8>: borsh::BorshDeserialize, | |
Vec<Vec<u8>>: borsh::BorshDeserialize, | |
bool: borsh::BorshDeserialize, | |
{ | |
fn deserialize( | |
buf: &mut &[u8], | |
) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | |
Ok(Self { | |
log_index: borsh::BorshDeserialize::deserialize(buf)?, | |
log_entry_data: borsh::BorshDeserialize::deserialize(buf)?, | |
receipt_index: borsh::BorshDeserialize::deserialize(buf)?, | |
receipt_data: borsh::BorshDeserialize::deserialize(buf)?, | |
header_data: borsh::BorshDeserialize::deserialize(buf)?, | |
proof: borsh::BorshDeserialize::deserialize(buf)?, | |
skip_bridge_call: borsh::BorshDeserialize::deserialize(buf)?, | |
}) | |
} | |
} | |
let Input { | |
log_index, | |
log_entry_data, | |
receipt_index, | |
receipt_data, | |
header_data, | |
proof, | |
skip_bridge_call, | |
}: Input = near_sdk::borsh::BorshDeserialize::try_from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from Borsh."); | |
let contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
let result = contract.verify_log_entry( | |
log_index, | |
log_entry_data, | |
receipt_index, | |
receipt_data, | |
header_data, | |
proof, | |
skip_bridge_call, | |
); | |
let result = near_sdk::borsh::BorshSerialize::try_to_vec(&result) | |
.expect("Failed to serialize the return value using Borsh."); | |
near_sdk::env::value_return(&result); | |
} | |
#[cfg(target_arch = "wasm32")] | |
#[no_mangle] | |
pub extern "C" fn set_bridge() { | |
near_sdk::env::setup_panic_hook(); | |
if near_sdk::env::attached_deposit() != 0 { | |
near_sdk::env::panic_str("Method set_bridge doesn\'t accept deposit"); | |
} | |
#[serde(crate = "near_sdk::serde")] | |
struct Input { | |
bridge: AccountId, | |
} | |
#[doc(hidden)] | |
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] | |
const _IMPL_DESERIALIZE_FOR_Input: () = { | |
use near_sdk::serde as _serde; | |
#[automatically_derived] | |
impl<'de> near_sdk::serde::Deserialize<'de> for Input { | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> near_sdk::serde::export::Result<Self, __D::Error> | |
where | |
__D: near_sdk::serde::Deserializer<'de>, | |
{ | |
#[allow(non_camel_case_types)] | |
enum __Field { | |
__field0, | |
__ignore, | |
} | |
struct __FieldVisitor; | |
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { | |
type Value = __Field; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "field identifier") | |
} | |
fn visit_u64<__E>( | |
self, | |
__value: u64, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
0u64 => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Err(_serde::de::Error::invalid_value( | |
_serde::de::Unexpected::Unsigned(__value), | |
&"field index 0 <= i < 1", | |
)), | |
} | |
} | |
fn visit_str<__E>( | |
self, | |
__value: &str, | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
"bridge" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
fn visit_bytes<__E>( | |
self, | |
__value: &[u8], | |
) -> _serde::export::Result<Self::Value, __E> | |
where | |
__E: _serde::de::Error, | |
{ | |
match __value { | |
b"bridge" => _serde::export::Ok(__Field::__field0), | |
_ => _serde::export::Ok(__Field::__ignore), | |
} | |
} | |
} | |
impl<'de> _serde::Deserialize<'de> for __Field { | |
#[inline] | |
fn deserialize<__D>( | |
__deserializer: __D, | |
) -> _serde::export::Result<Self, __D::Error> | |
where | |
__D: _serde::Deserializer<'de>, | |
{ | |
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) | |
} | |
} | |
struct __Visitor<'de> { | |
marker: _serde::export::PhantomData<Input>, | |
lifetime: _serde::export::PhantomData<&'de ()>, | |
} | |
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { | |
type Value = Input; | |
fn expecting( | |
&self, | |
__formatter: &mut _serde::export::Formatter, | |
) -> _serde::export::fmt::Result { | |
_serde::export::Formatter::write_str(__formatter, "struct Input") | |
} | |
#[inline] | |
fn visit_seq<__A>( | |
self, | |
mut __seq: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::SeqAccess<'de>, | |
{ | |
let __field0 = match match _serde::de::SeqAccess::next_element::<AccountId>( | |
&mut __seq, | |
) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} { | |
_serde::export::Some(__value) => __value, | |
_serde::export::None => { | |
return _serde::export::Err(_serde::de::Error::invalid_length( | |
0usize, | |
&"struct Input with 1 element", | |
)); | |
} | |
}; | |
_serde::export::Ok(Input { bridge: __field0 }) | |
} | |
#[inline] | |
fn visit_map<__A>( | |
self, | |
mut __map: __A, | |
) -> _serde::export::Result<Self::Value, __A::Error> | |
where | |
__A: _serde::de::MapAccess<'de>, | |
{ | |
let mut __field0: _serde::export::Option<AccountId> = _serde::export::None; | |
while let _serde::export::Some(__key) = | |
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
{ | |
match __key { | |
__Field::__field0 => { | |
if _serde::export::Option::is_some(&__field0) { | |
return _serde::export::Err( | |
<__A::Error as _serde::de::Error>::duplicate_field( | |
"bridge", | |
), | |
); | |
} | |
__field0 = _serde::export::Some( | |
match _serde::de::MapAccess::next_value::<AccountId>( | |
&mut __map, | |
) { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}, | |
); | |
} | |
_ => { | |
let _ = match _serde::de::MapAccess::next_value::< | |
_serde::de::IgnoredAny, | |
>(&mut __map) | |
{ | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
}; | |
} | |
} | |
} | |
let __field0 = match __field0 { | |
_serde::export::Some(__field0) => __field0, | |
_serde::export::None => { | |
match _serde::private::de::missing_field("bridge") { | |
_serde::export::Ok(__val) => __val, | |
_serde::export::Err(__err) => { | |
return _serde::export::Err(__err); | |
} | |
} | |
} | |
}; | |
_serde::export::Ok(Input { bridge: __field0 }) | |
} | |
} | |
const FIELDS: &'static [&'static str] = &["bridge"]; | |
_serde::Deserializer::deserialize_struct( | |
__deserializer, | |
"Input", | |
FIELDS, | |
__Visitor { | |
marker: _serde::export::PhantomData::<Input>, | |
lifetime: _serde::export::PhantomData, | |
}, | |
) | |
} | |
} | |
}; | |
let Input { bridge }: Input = near_sdk::serde_json::from_slice( | |
&near_sdk::env::input().expect("Expected input since method has arguments."), | |
) | |
.expect("Failed to deserialize input from JSON."); | |
let mut contract: EthProver = near_sdk::env::state_read().unwrap_or_default(); | |
contract.set_bridge(bridge); | |
near_sdk::env::state_write(&contract); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment