@mainsail/evm 0.0.1-evm.51 → 0.0.1-evm.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +5922 -0
- package/Cargo.toml +34 -0
- package/bindings/Cargo.toml +33 -0
- package/bindings/build.rs +6 -0
- package/bindings/src/ctx.rs +667 -0
- package/bindings/src/lib.rs +2231 -0
- package/bindings/src/logger.rs +110 -0
- package/bindings/src/result.rs +542 -0
- package/bindings/src/utils.rs +71 -0
- package/core/Cargo.toml +36 -0
- package/core/src/account.rs +112 -0
- package/core/src/bytecode.rs +39 -0
- package/core/src/compression.rs +158 -0
- package/core/src/db.rs +3311 -0
- package/core/src/events.rs +9 -0
- package/core/src/historical.rs +544 -0
- package/core/src/legacy.rs +153 -0
- package/core/src/lib.rs +14 -0
- package/core/src/logger.rs +98 -0
- package/core/src/logs_bloom.rs +96 -0
- package/core/src/precompiles.rs +450 -0
- package/core/src/receipt.rs +153 -0
- package/core/src/state_changes.rs +122 -0
- package/core/src/state_commit.rs +615 -0
- package/core/src/state_root.rs +266 -0
- package/index.d.ts +1 -0
- package/index.js +52 -52
- package/package.json +5 -4
- package/scripts/postinstall.mjs +73 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
use revm::{
|
|
2
|
+
context::result::{ExecutionResult, Output},
|
|
3
|
+
primitives::{Bytes, Log},
|
|
4
|
+
};
|
|
5
|
+
use serde::{Deserialize, Serialize};
|
|
6
|
+
|
|
7
|
+
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
|
8
|
+
pub struct TxReceipt {
|
|
9
|
+
pub gas_used: u64,
|
|
10
|
+
pub cumulative_gas_used: u64,
|
|
11
|
+
pub gas_refunded: u64,
|
|
12
|
+
pub success: u8,
|
|
13
|
+
pub contract_address: Option<String>,
|
|
14
|
+
pub logs: Option<Vec<Log>>,
|
|
15
|
+
pub output: Option<Bytes>,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
pub fn map_execution_result(result: ExecutionResult, cumulative_gas_used: u64) -> TxReceipt {
|
|
19
|
+
match result {
|
|
20
|
+
ExecutionResult::Success {
|
|
21
|
+
gas, output, logs, ..
|
|
22
|
+
} => match output {
|
|
23
|
+
Output::Call(output) => TxReceipt {
|
|
24
|
+
gas_used: gas.tx_gas_used(),
|
|
25
|
+
gas_refunded: gas.inner_refunded(),
|
|
26
|
+
cumulative_gas_used,
|
|
27
|
+
success: 1,
|
|
28
|
+
contract_address: None,
|
|
29
|
+
logs: Some(logs),
|
|
30
|
+
output: Some(output),
|
|
31
|
+
},
|
|
32
|
+
Output::Create(output, address) => TxReceipt {
|
|
33
|
+
gas_used: gas.tx_gas_used(),
|
|
34
|
+
gas_refunded: gas.inner_refunded(),
|
|
35
|
+
cumulative_gas_used,
|
|
36
|
+
success: 1,
|
|
37
|
+
contract_address: address.map(|address| address.to_string()),
|
|
38
|
+
logs: Some(logs),
|
|
39
|
+
output: Some(output),
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
ExecutionResult::Revert { gas, output, .. } => TxReceipt {
|
|
43
|
+
gas_used: gas.tx_gas_used(),
|
|
44
|
+
success: 0,
|
|
45
|
+
cumulative_gas_used,
|
|
46
|
+
gas_refunded: 0,
|
|
47
|
+
contract_address: None,
|
|
48
|
+
logs: None,
|
|
49
|
+
output: Some(output),
|
|
50
|
+
},
|
|
51
|
+
ExecutionResult::Halt { gas, .. } => TxReceipt {
|
|
52
|
+
gas_used: gas.tx_gas_used(),
|
|
53
|
+
success: 0,
|
|
54
|
+
cumulative_gas_used,
|
|
55
|
+
gas_refunded: 0,
|
|
56
|
+
contract_address: None,
|
|
57
|
+
logs: None,
|
|
58
|
+
output: None,
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
#[cfg(test)]
|
|
64
|
+
mod tests {
|
|
65
|
+
use crate::receipt::map_execution_result;
|
|
66
|
+
use alloy_primitives::address;
|
|
67
|
+
use bytes::Bytes;
|
|
68
|
+
use revm::context::result::{ExecutionResult, HaltReason, Output, ResultGas, SuccessReason};
|
|
69
|
+
|
|
70
|
+
#[test]
|
|
71
|
+
fn test_map_execution_result_call() {
|
|
72
|
+
let result = ExecutionResult::Success {
|
|
73
|
+
reason: SuccessReason::Stop,
|
|
74
|
+
gas: ResultGas::new_with_state_gas(25000, 2100, 0, 0),
|
|
75
|
+
logs: vec![],
|
|
76
|
+
output: Output::Call(alloy_primitives::Bytes(Bytes::new())),
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
let output = map_execution_result(result, 0);
|
|
80
|
+
|
|
81
|
+
assert_eq!(output.contract_address, None);
|
|
82
|
+
assert_eq!(output.gas_used, 22900);
|
|
83
|
+
assert_eq!(output.cumulative_gas_used, 0);
|
|
84
|
+
assert_eq!(output.gas_refunded, 2100);
|
|
85
|
+
assert_eq!(output.logs, Some(vec![]));
|
|
86
|
+
assert_eq!(output.output, Some(alloy_primitives::Bytes(Bytes::new())));
|
|
87
|
+
assert_eq!(output.success, 1);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
#[test]
|
|
91
|
+
fn test_map_execution_result_create() {
|
|
92
|
+
let result = ExecutionResult::Success {
|
|
93
|
+
reason: SuccessReason::Stop,
|
|
94
|
+
gas: ResultGas::new_with_state_gas(355_000, 0, 0, 0),
|
|
95
|
+
logs: vec![],
|
|
96
|
+
output: Output::Create(
|
|
97
|
+
alloy_primitives::Bytes(Bytes::new()),
|
|
98
|
+
Some(address!("0000000000000000000000000000000000000001")),
|
|
99
|
+
),
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
let output = map_execution_result(result, 0);
|
|
103
|
+
|
|
104
|
+
assert_eq!(
|
|
105
|
+
output.contract_address,
|
|
106
|
+
Some(address!("0000000000000000000000000000000000000001").to_string())
|
|
107
|
+
);
|
|
108
|
+
assert_eq!(output.gas_used, 355_000);
|
|
109
|
+
assert_eq!(output.cumulative_gas_used, 0);
|
|
110
|
+
assert_eq!(output.gas_refunded, 0);
|
|
111
|
+
assert_eq!(output.logs, Some(vec![]));
|
|
112
|
+
assert_eq!(output.output, Some(alloy_primitives::Bytes(Bytes::new())));
|
|
113
|
+
assert_eq!(output.success, 1);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
#[test]
|
|
117
|
+
fn test_map_execution_result_revert() {
|
|
118
|
+
let result = ExecutionResult::Revert {
|
|
119
|
+
gas: ResultGas::new_with_state_gas(30000, 0, 0, 0),
|
|
120
|
+
logs: vec![],
|
|
121
|
+
output: alloy_primitives::Bytes(Bytes::new()),
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
let output = map_execution_result(result, 0);
|
|
125
|
+
|
|
126
|
+
assert_eq!(output.contract_address, None);
|
|
127
|
+
assert_eq!(output.gas_used, 30000);
|
|
128
|
+
assert_eq!(output.cumulative_gas_used, 0);
|
|
129
|
+
assert_eq!(output.gas_refunded, 0);
|
|
130
|
+
assert_eq!(output.logs, None);
|
|
131
|
+
assert_eq!(output.output, Some(alloy_primitives::Bytes(Bytes::new())));
|
|
132
|
+
assert_eq!(output.success, 0);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
#[test]
|
|
136
|
+
fn test_map_execution_result_halt() {
|
|
137
|
+
let result = ExecutionResult::Halt {
|
|
138
|
+
reason: HaltReason::StackOverflow,
|
|
139
|
+
gas: ResultGas::new_with_state_gas(30000, 0, 0, 0),
|
|
140
|
+
logs: vec![],
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
let output = map_execution_result(result, 0);
|
|
144
|
+
|
|
145
|
+
assert_eq!(output.contract_address, None);
|
|
146
|
+
assert_eq!(output.gas_used, 30000);
|
|
147
|
+
assert_eq!(output.cumulative_gas_used, 0);
|
|
148
|
+
assert_eq!(output.gas_refunded, 0);
|
|
149
|
+
assert_eq!(output.logs, None);
|
|
150
|
+
assert_eq!(output.output, None);
|
|
151
|
+
assert_eq!(output.success, 0);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
use std::collections::BTreeMap;
|
|
2
|
+
|
|
3
|
+
use revm::{
|
|
4
|
+
database::{BundleState, OriginalValuesKnown, states::StorageSlot},
|
|
5
|
+
primitives::{Address, B256, KECCAK_EMPTY, U256},
|
|
6
|
+
state::{AccountInfo, Bytecode},
|
|
7
|
+
};
|
|
8
|
+
use serde::Serialize;
|
|
9
|
+
|
|
10
|
+
use crate::legacy::{LegacyAccountAttributes, LegacyAddress, LegacyColdWallet};
|
|
11
|
+
|
|
12
|
+
/// Loosely based on https://github.com/bluealloy/revm/blob/v36/crates/revm/src/db/states/changes.rs and https://github.com/bluealloy/revm/blob/v36/crates/revm/src/db/states/bundle_state.rs#L449
|
|
13
|
+
//
|
|
14
|
+
/// The only change being that we preserve the old storage value.
|
|
15
|
+
#[derive(Clone, Debug, Default, Serialize)]
|
|
16
|
+
pub struct StateChangeset {
|
|
17
|
+
/// Vector of **not** sorted accounts information.
|
|
18
|
+
pub accounts: Vec<(Address, Option<AccountInfo>)>,
|
|
19
|
+
/// Vector of **not** sorted storage.
|
|
20
|
+
pub storage: Vec<StorageChangeset>,
|
|
21
|
+
/// Vector of contracts by bytecode hash. **not** sorted.
|
|
22
|
+
pub contracts: Vec<(B256, Bytecode)>,
|
|
23
|
+
// Map of legacy attributes
|
|
24
|
+
pub legacy_attributes: BTreeMap<Address, LegacyAccountAttributes>,
|
|
25
|
+
// Map of legacy cold wallet
|
|
26
|
+
pub legacy_cold_wallets: BTreeMap<LegacyAddress, LegacyColdWallet>,
|
|
27
|
+
// Map of merged legacy cold wallets
|
|
28
|
+
pub merged_legacy_cold_wallets: BTreeMap<Address, (B256, LegacyAddress)>,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
#[derive(Clone, Debug, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
|
|
32
|
+
pub struct StorageChangeset {
|
|
33
|
+
/// Address of account
|
|
34
|
+
pub address: Address,
|
|
35
|
+
/// Wipe storage,
|
|
36
|
+
pub wipe_storage: bool,
|
|
37
|
+
/// Storage key value pairs.
|
|
38
|
+
pub storage: Vec<(U256, StorageSlot)>,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
#[derive(Default, Debug, PartialEq, Eq)]
|
|
42
|
+
pub struct AccountUpdate {
|
|
43
|
+
pub address: Address,
|
|
44
|
+
pub balance: U256,
|
|
45
|
+
pub nonce: u64,
|
|
46
|
+
// Set when commit receipt contains "Voted" event
|
|
47
|
+
pub vote: Option<Address>,
|
|
48
|
+
// Set when commit receipt contains "Unvoted" event
|
|
49
|
+
pub unvote: Option<Address>,
|
|
50
|
+
// Set when commit receipt contains "UsernameRegistered" event
|
|
51
|
+
pub username: Option<String>,
|
|
52
|
+
// Set when commit receipt contains "UsernameResigned" event
|
|
53
|
+
pub username_resigned: bool,
|
|
54
|
+
// Set when merge with legacy cold wallet happened
|
|
55
|
+
pub merge_info: Option<AccountMergeInfo>,
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
#[derive(Default, Debug, PartialEq, Eq)]
|
|
59
|
+
pub struct AccountMergeInfo {
|
|
60
|
+
pub legacy_address: LegacyAddress,
|
|
61
|
+
pub transaction_hash: B256,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
pub fn bundle_into_change_set(bundle_state: BundleState) -> StateChangeset {
|
|
65
|
+
let is_value_known = OriginalValuesKnown::Yes;
|
|
66
|
+
|
|
67
|
+
let state_len = bundle_state.state.len();
|
|
68
|
+
let mut accounts = Vec::with_capacity(state_len);
|
|
69
|
+
let mut storage = Vec::with_capacity(state_len);
|
|
70
|
+
|
|
71
|
+
for (address, account) in bundle_state.state {
|
|
72
|
+
// append account info if it is changed.
|
|
73
|
+
let was_destroyed = account.was_destroyed();
|
|
74
|
+
if is_value_known.is_not_known() || account.is_info_changed() {
|
|
75
|
+
let info = account.info.map(AccountInfo::without_code);
|
|
76
|
+
accounts.push((address, info));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// append storage changes
|
|
80
|
+
|
|
81
|
+
// NOTE: Assumption is that revert is going to remove whole plain storage from
|
|
82
|
+
// database so we can check if plain state was wiped or not.
|
|
83
|
+
let mut account_storage_changed = Vec::with_capacity(account.storage.len());
|
|
84
|
+
|
|
85
|
+
for (key, slot) in account.storage {
|
|
86
|
+
// If storage was destroyed that means that storage was wiped.
|
|
87
|
+
// In that case we need to check if present storage value is different then ZERO.
|
|
88
|
+
let destroyed_and_not_zero = was_destroyed && slot.present_value != U256::ZERO;
|
|
89
|
+
|
|
90
|
+
// If account is not destroyed check if original values was changed,
|
|
91
|
+
// so we can update it.
|
|
92
|
+
let not_destroyed_and_changed = !was_destroyed && slot.is_changed();
|
|
93
|
+
|
|
94
|
+
if is_value_known.is_not_known() || destroyed_and_not_zero || not_destroyed_and_changed
|
|
95
|
+
{
|
|
96
|
+
account_storage_changed.push((key, slot));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if !account_storage_changed.is_empty() || was_destroyed {
|
|
101
|
+
// append storage changes to account.
|
|
102
|
+
storage.push(StorageChangeset {
|
|
103
|
+
address,
|
|
104
|
+
wipe_storage: was_destroyed,
|
|
105
|
+
storage: account_storage_changed,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
let contracts = bundle_state
|
|
110
|
+
.contracts
|
|
111
|
+
.into_iter()
|
|
112
|
+
// remove empty bytecodes
|
|
113
|
+
.filter(|(b, _)| *b != KECCAK_EMPTY)
|
|
114
|
+
.collect::<Vec<_>>();
|
|
115
|
+
|
|
116
|
+
StateChangeset {
|
|
117
|
+
accounts,
|
|
118
|
+
storage,
|
|
119
|
+
contracts,
|
|
120
|
+
..Default::default()
|
|
121
|
+
}
|
|
122
|
+
}
|