@mainsail/evm 0.0.1-evm.52 → 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,9 @@
|
|
|
1
|
+
use alloy_sol_types::sol;
|
|
2
|
+
|
|
3
|
+
sol! {
|
|
4
|
+
event Voted(address voter, address validator);
|
|
5
|
+
event Unvoted(address voter, address validator);
|
|
6
|
+
|
|
7
|
+
event UsernameRegistered(address addr, string username, string previousUsername);
|
|
8
|
+
event UsernameResigned(address addr, string username);
|
|
9
|
+
}
|
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
use std::collections::BTreeMap;
|
|
2
|
+
|
|
3
|
+
use heed::{RoTxn, RwTxn};
|
|
4
|
+
use revm::{
|
|
5
|
+
primitives::{Address, B256, U256},
|
|
6
|
+
state::AccountInfo,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
use crate::{compression::CompactBincode, db::Error};
|
|
10
|
+
|
|
11
|
+
#[derive(Clone, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
|
12
|
+
pub struct HistoricalAccountData {
|
|
13
|
+
pub balance: U256,
|
|
14
|
+
pub nonce: u64,
|
|
15
|
+
pub code_hash: B256,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
impl From<AccountInfo> for HistoricalAccountData {
|
|
19
|
+
fn from(value: AccountInfo) -> Self {
|
|
20
|
+
HistoricalAccountData {
|
|
21
|
+
balance: value.balance,
|
|
22
|
+
nonce: value.nonce,
|
|
23
|
+
code_hash: value.code_hash,
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
pub struct AccountHistory {
|
|
29
|
+
capacity: u64,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
impl AccountHistory {
|
|
33
|
+
pub fn new(capacity: u64) -> Self {
|
|
34
|
+
Self { capacity }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
pub fn insert(
|
|
38
|
+
&self,
|
|
39
|
+
txn: &mut RwTxn,
|
|
40
|
+
database: &heed::Database<
|
|
41
|
+
heed::types::U64<heed::byteorder::BigEndian>,
|
|
42
|
+
CompactBincode<BTreeMap<Address, HistoricalAccountData>>,
|
|
43
|
+
>,
|
|
44
|
+
block_number: u64,
|
|
45
|
+
accounts: Vec<(Address, AccountInfo)>,
|
|
46
|
+
) -> Result<(), Error> {
|
|
47
|
+
assert!(database.get(txn, &block_number)?.is_none());
|
|
48
|
+
|
|
49
|
+
let count = database.len(txn)?;
|
|
50
|
+
if count >= self.capacity {
|
|
51
|
+
// delete oldest entries
|
|
52
|
+
let range = ..=block_number.saturating_sub(self.capacity);
|
|
53
|
+
database.delete_range(txn, &range)?;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let data = accounts
|
|
57
|
+
.into_iter()
|
|
58
|
+
.map(|a| (a.0, HistoricalAccountData::from(a.1)))
|
|
59
|
+
.collect::<BTreeMap<Address, HistoricalAccountData>>();
|
|
60
|
+
|
|
61
|
+
database.put(txn, &block_number, &CompactBincode(&data))?;
|
|
62
|
+
|
|
63
|
+
Ok(())
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
pub fn get_by_block_and_address(
|
|
67
|
+
&self,
|
|
68
|
+
txn: &RoTxn,
|
|
69
|
+
database: &heed::Database<
|
|
70
|
+
heed::types::U64<heed::byteorder::BigEndian>,
|
|
71
|
+
CompactBincode<BTreeMap<Address, HistoricalAccountData>>,
|
|
72
|
+
>,
|
|
73
|
+
block_number: u64,
|
|
74
|
+
address: &Address,
|
|
75
|
+
) -> Result<(Option<HistoricalAccountData>, bool), Error> {
|
|
76
|
+
let mut iter = database.rev_range(txn, &..=block_number)?;
|
|
77
|
+
|
|
78
|
+
let mut missing_fallback = false;
|
|
79
|
+
|
|
80
|
+
while let Some((_, history)) = iter.next().transpose()? {
|
|
81
|
+
if let Some(data) = history.get(address) {
|
|
82
|
+
return Ok((Some(data.clone()), false));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
missing_fallback = true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
Ok((None, missing_fallback))
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
#[test]
|
|
93
|
+
fn test_account_history() {
|
|
94
|
+
let path = tempfile::Builder::new()
|
|
95
|
+
.prefix("evm.mdb")
|
|
96
|
+
.tempdir()
|
|
97
|
+
.unwrap();
|
|
98
|
+
|
|
99
|
+
let db = crate::db::PersistentDB::new(
|
|
100
|
+
crate::db::PersistentDBOptions::new(path.path().to_path_buf()).with_history_size(10),
|
|
101
|
+
)
|
|
102
|
+
.expect("database");
|
|
103
|
+
|
|
104
|
+
let history = AccountHistory::new(10);
|
|
105
|
+
let mut txn = db.env.write_txn().unwrap();
|
|
106
|
+
|
|
107
|
+
let history_db = &db.inner.borrow().accounts_history.unwrap();
|
|
108
|
+
|
|
109
|
+
// Block 1
|
|
110
|
+
history
|
|
111
|
+
.insert(
|
|
112
|
+
&mut txn,
|
|
113
|
+
history_db,
|
|
114
|
+
1,
|
|
115
|
+
vec![
|
|
116
|
+
(
|
|
117
|
+
revm::primitives::address!("0000000000000000000000000000000000000001"),
|
|
118
|
+
AccountInfo {
|
|
119
|
+
balance: U256::from(1),
|
|
120
|
+
nonce: 1,
|
|
121
|
+
..Default::default()
|
|
122
|
+
},
|
|
123
|
+
),
|
|
124
|
+
(
|
|
125
|
+
revm::primitives::address!("0000000000000000000000000000000000000002"),
|
|
126
|
+
AccountInfo {
|
|
127
|
+
balance: U256::from(2),
|
|
128
|
+
nonce: 1,
|
|
129
|
+
..Default::default()
|
|
130
|
+
},
|
|
131
|
+
),
|
|
132
|
+
],
|
|
133
|
+
)
|
|
134
|
+
.unwrap();
|
|
135
|
+
|
|
136
|
+
// Block 2
|
|
137
|
+
history
|
|
138
|
+
.insert(
|
|
139
|
+
&mut txn,
|
|
140
|
+
history_db,
|
|
141
|
+
2,
|
|
142
|
+
vec![
|
|
143
|
+
(
|
|
144
|
+
revm::primitives::address!("0000000000000000000000000000000000000001"),
|
|
145
|
+
AccountInfo {
|
|
146
|
+
balance: U256::from(2),
|
|
147
|
+
nonce: 1,
|
|
148
|
+
..Default::default()
|
|
149
|
+
},
|
|
150
|
+
),
|
|
151
|
+
(
|
|
152
|
+
revm::primitives::address!("0000000000000000000000000000000000000003"),
|
|
153
|
+
AccountInfo {
|
|
154
|
+
balance: U256::from(3),
|
|
155
|
+
nonce: 3,
|
|
156
|
+
..Default::default()
|
|
157
|
+
},
|
|
158
|
+
),
|
|
159
|
+
],
|
|
160
|
+
)
|
|
161
|
+
.unwrap();
|
|
162
|
+
|
|
163
|
+
// Block 3 - 4 (empty)
|
|
164
|
+
history.insert(&mut txn, history_db, 3, vec![]).unwrap();
|
|
165
|
+
history.insert(&mut txn, history_db, 4, vec![]).unwrap();
|
|
166
|
+
|
|
167
|
+
// Block 5
|
|
168
|
+
history
|
|
169
|
+
.insert(
|
|
170
|
+
&mut txn,
|
|
171
|
+
history_db,
|
|
172
|
+
5,
|
|
173
|
+
vec![
|
|
174
|
+
(
|
|
175
|
+
revm::primitives::address!("0000000000000000000000000000000000000001"),
|
|
176
|
+
AccountInfo {
|
|
177
|
+
balance: U256::from(5),
|
|
178
|
+
nonce: 5,
|
|
179
|
+
..Default::default()
|
|
180
|
+
},
|
|
181
|
+
),
|
|
182
|
+
(
|
|
183
|
+
revm::primitives::address!("0000000000000000000000000000000000000004"),
|
|
184
|
+
AccountInfo {
|
|
185
|
+
balance: U256::from(4),
|
|
186
|
+
nonce: 4,
|
|
187
|
+
..Default::default()
|
|
188
|
+
},
|
|
189
|
+
),
|
|
190
|
+
],
|
|
191
|
+
)
|
|
192
|
+
.unwrap();
|
|
193
|
+
|
|
194
|
+
// Assert Account 1 at respective blocks (1 - 5)
|
|
195
|
+
for (block_number, address, balance, nonce) in vec![
|
|
196
|
+
// Block 1
|
|
197
|
+
(
|
|
198
|
+
1,
|
|
199
|
+
revm::primitives::address!("0000000000000000000000000000000000000001"),
|
|
200
|
+
U256::from(1),
|
|
201
|
+
1,
|
|
202
|
+
),
|
|
203
|
+
// Block 2
|
|
204
|
+
(
|
|
205
|
+
2,
|
|
206
|
+
revm::primitives::address!("0000000000000000000000000000000000000001"),
|
|
207
|
+
U256::from(2),
|
|
208
|
+
1,
|
|
209
|
+
),
|
|
210
|
+
// Block 3 (unchanged since block_number 2)
|
|
211
|
+
(
|
|
212
|
+
3,
|
|
213
|
+
revm::primitives::address!("0000000000000000000000000000000000000001"),
|
|
214
|
+
U256::from(2),
|
|
215
|
+
1,
|
|
216
|
+
),
|
|
217
|
+
// Block 4 (unchanged since block_number 2)
|
|
218
|
+
(
|
|
219
|
+
4,
|
|
220
|
+
revm::primitives::address!("0000000000000000000000000000000000000001"),
|
|
221
|
+
U256::from(2),
|
|
222
|
+
1,
|
|
223
|
+
),
|
|
224
|
+
// Block 5
|
|
225
|
+
(
|
|
226
|
+
5,
|
|
227
|
+
revm::primitives::address!("0000000000000000000000000000000000000001"),
|
|
228
|
+
U256::from(5),
|
|
229
|
+
5,
|
|
230
|
+
),
|
|
231
|
+
] {
|
|
232
|
+
let account = history
|
|
233
|
+
.get_by_block_and_address(&mut txn, history_db, block_number, &address)
|
|
234
|
+
.unwrap();
|
|
235
|
+
|
|
236
|
+
assert!(account.0.is_some_and(|a| a
|
|
237
|
+
== HistoricalAccountData {
|
|
238
|
+
balance: balance,
|
|
239
|
+
nonce: nonce,
|
|
240
|
+
code_hash: revm::primitives::KECCAK_EMPTY,
|
|
241
|
+
}));
|
|
242
|
+
assert_eq!(account.1, false);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Assert Account 2 at respective block_numbers (1 - 5)
|
|
246
|
+
for (block_number, address, balance, nonce) in vec![
|
|
247
|
+
// Block 1
|
|
248
|
+
(
|
|
249
|
+
1,
|
|
250
|
+
revm::primitives::address!("0000000000000000000000000000000000000002"),
|
|
251
|
+
U256::from(2),
|
|
252
|
+
1,
|
|
253
|
+
),
|
|
254
|
+
// Block 2 (unchanged since block_number 1)
|
|
255
|
+
(
|
|
256
|
+
2,
|
|
257
|
+
revm::primitives::address!("0000000000000000000000000000000000000002"),
|
|
258
|
+
U256::from(2),
|
|
259
|
+
1,
|
|
260
|
+
),
|
|
261
|
+
// Block 3 (unchanged since block_number 1)
|
|
262
|
+
(
|
|
263
|
+
3,
|
|
264
|
+
revm::primitives::address!("0000000000000000000000000000000000000002"),
|
|
265
|
+
U256::from(2),
|
|
266
|
+
1,
|
|
267
|
+
),
|
|
268
|
+
// Block 4 (unchanged since block_number 1)
|
|
269
|
+
(
|
|
270
|
+
4,
|
|
271
|
+
revm::primitives::address!("0000000000000000000000000000000000000002"),
|
|
272
|
+
U256::from(2),
|
|
273
|
+
1,
|
|
274
|
+
),
|
|
275
|
+
// Block 5 (unchanged since block_number 1)
|
|
276
|
+
(
|
|
277
|
+
5,
|
|
278
|
+
revm::primitives::address!("0000000000000000000000000000000000000002"),
|
|
279
|
+
U256::from(2),
|
|
280
|
+
1,
|
|
281
|
+
),
|
|
282
|
+
] {
|
|
283
|
+
let account = history
|
|
284
|
+
.get_by_block_and_address(&mut txn, history_db, block_number, &address)
|
|
285
|
+
.unwrap();
|
|
286
|
+
|
|
287
|
+
assert!(account.0.is_some_and(|a| a
|
|
288
|
+
== HistoricalAccountData {
|
|
289
|
+
balance: balance,
|
|
290
|
+
nonce: nonce,
|
|
291
|
+
code_hash: revm::primitives::KECCAK_EMPTY,
|
|
292
|
+
}));
|
|
293
|
+
assert_eq!(account.1, false);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Assert Account 3 at respective block_numbers (1 - 5)
|
|
297
|
+
for (block_number, address) in vec![
|
|
298
|
+
// Block 1 - non existent
|
|
299
|
+
(
|
|
300
|
+
1,
|
|
301
|
+
revm::primitives::address!("0000000000000000000000000000000000000003"),
|
|
302
|
+
),
|
|
303
|
+
] {
|
|
304
|
+
let account = history
|
|
305
|
+
.get_by_block_and_address(&mut txn, history_db, block_number, &address)
|
|
306
|
+
.unwrap();
|
|
307
|
+
assert_eq!(account, (None, true));
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
for (block_number, address, balance, nonce) in vec![
|
|
311
|
+
// Block 2
|
|
312
|
+
(
|
|
313
|
+
2,
|
|
314
|
+
revm::primitives::address!("0000000000000000000000000000000000000003"),
|
|
315
|
+
U256::from(3),
|
|
316
|
+
3,
|
|
317
|
+
),
|
|
318
|
+
// Block 3 (unchanged since block_number 2)
|
|
319
|
+
(
|
|
320
|
+
3,
|
|
321
|
+
revm::primitives::address!("0000000000000000000000000000000000000003"),
|
|
322
|
+
U256::from(3),
|
|
323
|
+
3,
|
|
324
|
+
),
|
|
325
|
+
// Block 4 (unchanged since block_number 2)
|
|
326
|
+
(
|
|
327
|
+
4,
|
|
328
|
+
revm::primitives::address!("0000000000000000000000000000000000000003"),
|
|
329
|
+
U256::from(3),
|
|
330
|
+
3,
|
|
331
|
+
),
|
|
332
|
+
// Block 5 (unchanged since block_number 2)
|
|
333
|
+
(
|
|
334
|
+
5,
|
|
335
|
+
revm::primitives::address!("0000000000000000000000000000000000000003"),
|
|
336
|
+
U256::from(3),
|
|
337
|
+
3,
|
|
338
|
+
),
|
|
339
|
+
] {
|
|
340
|
+
let account = history
|
|
341
|
+
.get_by_block_and_address(&mut txn, history_db, block_number, &address)
|
|
342
|
+
.unwrap();
|
|
343
|
+
|
|
344
|
+
assert!(account.0.is_some_and(|a| a
|
|
345
|
+
== HistoricalAccountData {
|
|
346
|
+
balance: balance,
|
|
347
|
+
nonce: nonce,
|
|
348
|
+
code_hash: revm::primitives::KECCAK_EMPTY,
|
|
349
|
+
}));
|
|
350
|
+
assert_eq!(account.1, false);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Assert Account 4 at respective block_numbers (1 - 5)
|
|
354
|
+
for (block_number, address) in vec![
|
|
355
|
+
// Block 1 - non existent
|
|
356
|
+
(
|
|
357
|
+
1,
|
|
358
|
+
revm::primitives::address!("0000000000000000000000000000000000000004"),
|
|
359
|
+
),
|
|
360
|
+
(
|
|
361
|
+
2,
|
|
362
|
+
revm::primitives::address!("0000000000000000000000000000000000000004"),
|
|
363
|
+
),
|
|
364
|
+
(
|
|
365
|
+
3,
|
|
366
|
+
revm::primitives::address!("0000000000000000000000000000000000000004"),
|
|
367
|
+
),
|
|
368
|
+
(
|
|
369
|
+
4,
|
|
370
|
+
revm::primitives::address!("0000000000000000000000000000000000000004"),
|
|
371
|
+
),
|
|
372
|
+
] {
|
|
373
|
+
let account = history
|
|
374
|
+
.get_by_block_and_address(&mut txn, history_db, block_number, &address)
|
|
375
|
+
.unwrap();
|
|
376
|
+
assert!(account.0.is_none());
|
|
377
|
+
assert_eq!(account.1, true);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
for (block_number, address, balance, nonce) in vec![
|
|
381
|
+
// Block 5
|
|
382
|
+
(
|
|
383
|
+
5,
|
|
384
|
+
revm::primitives::address!("0000000000000000000000000000000000000004"),
|
|
385
|
+
U256::from(4),
|
|
386
|
+
4,
|
|
387
|
+
),
|
|
388
|
+
] {
|
|
389
|
+
let account = history
|
|
390
|
+
.get_by_block_and_address(&mut txn, history_db, block_number, &address)
|
|
391
|
+
.unwrap();
|
|
392
|
+
|
|
393
|
+
assert!(account.0.is_some_and(|a| a
|
|
394
|
+
== HistoricalAccountData {
|
|
395
|
+
balance: balance,
|
|
396
|
+
nonce: nonce,
|
|
397
|
+
code_hash: revm::primitives::KECCAK_EMPTY,
|
|
398
|
+
}));
|
|
399
|
+
assert_eq!(account.1, false);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
#[test]
|
|
404
|
+
fn test_accounts_history_capacity() {
|
|
405
|
+
let path = tempfile::Builder::new()
|
|
406
|
+
.prefix("evm.mdb")
|
|
407
|
+
.tempdir()
|
|
408
|
+
.unwrap();
|
|
409
|
+
|
|
410
|
+
let db = crate::db::PersistentDB::new(
|
|
411
|
+
crate::db::PersistentDBOptions::new(path.path().to_path_buf()).with_history_size(3),
|
|
412
|
+
)
|
|
413
|
+
.expect("database");
|
|
414
|
+
|
|
415
|
+
let history = AccountHistory::new(3);
|
|
416
|
+
let mut txn = db.env.write_txn().unwrap();
|
|
417
|
+
|
|
418
|
+
let history_db = &db.inner.borrow().accounts_history.unwrap();
|
|
419
|
+
|
|
420
|
+
for i in 0..5 {
|
|
421
|
+
println!("writing i... {}", i);
|
|
422
|
+
// Block 1
|
|
423
|
+
history
|
|
424
|
+
.insert(
|
|
425
|
+
&mut txn,
|
|
426
|
+
history_db,
|
|
427
|
+
i as u64,
|
|
428
|
+
vec![
|
|
429
|
+
(
|
|
430
|
+
revm::primitives::address!("0000000000000000000000000000000000000001"),
|
|
431
|
+
AccountInfo {
|
|
432
|
+
balance: U256::from(i),
|
|
433
|
+
nonce: i,
|
|
434
|
+
..Default::default()
|
|
435
|
+
},
|
|
436
|
+
),
|
|
437
|
+
(
|
|
438
|
+
revm::primitives::address!("0000000000000000000000000000000000000002"),
|
|
439
|
+
AccountInfo {
|
|
440
|
+
balance: U256::from(i + 2),
|
|
441
|
+
nonce: i + 2,
|
|
442
|
+
..Default::default()
|
|
443
|
+
},
|
|
444
|
+
),
|
|
445
|
+
],
|
|
446
|
+
)
|
|
447
|
+
.unwrap();
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Assert accounts not available below capacity
|
|
451
|
+
for (block_number, address) in vec![
|
|
452
|
+
// Block 0
|
|
453
|
+
(
|
|
454
|
+
0,
|
|
455
|
+
revm::primitives::address!("0000000000000000000000000000000000000001"),
|
|
456
|
+
),
|
|
457
|
+
// Block 1
|
|
458
|
+
(
|
|
459
|
+
1,
|
|
460
|
+
revm::primitives::address!("0000000000000000000000000000000000000001"),
|
|
461
|
+
),
|
|
462
|
+
] {
|
|
463
|
+
let account = history
|
|
464
|
+
.get_by_block_and_address(&mut txn, history_db, block_number, &address)
|
|
465
|
+
.unwrap();
|
|
466
|
+
assert_eq!(account, (None, false));
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// Assert accounts found at respective block_numbers (2+)
|
|
470
|
+
for (block_number, address, balance, nonce) in vec![
|
|
471
|
+
// Block 2
|
|
472
|
+
(
|
|
473
|
+
2,
|
|
474
|
+
revm::primitives::address!("0000000000000000000000000000000000000001"),
|
|
475
|
+
U256::from(2),
|
|
476
|
+
2,
|
|
477
|
+
),
|
|
478
|
+
(
|
|
479
|
+
2,
|
|
480
|
+
revm::primitives::address!("0000000000000000000000000000000000000002"),
|
|
481
|
+
U256::from(4),
|
|
482
|
+
4,
|
|
483
|
+
),
|
|
484
|
+
// Block 3
|
|
485
|
+
(
|
|
486
|
+
3,
|
|
487
|
+
revm::primitives::address!("0000000000000000000000000000000000000001"),
|
|
488
|
+
U256::from(3),
|
|
489
|
+
3,
|
|
490
|
+
),
|
|
491
|
+
(
|
|
492
|
+
3,
|
|
493
|
+
revm::primitives::address!("0000000000000000000000000000000000000002"),
|
|
494
|
+
U256::from(5),
|
|
495
|
+
5,
|
|
496
|
+
),
|
|
497
|
+
// Block 4
|
|
498
|
+
(
|
|
499
|
+
4,
|
|
500
|
+
revm::primitives::address!("0000000000000000000000000000000000000001"),
|
|
501
|
+
U256::from(4),
|
|
502
|
+
4,
|
|
503
|
+
),
|
|
504
|
+
(
|
|
505
|
+
4,
|
|
506
|
+
revm::primitives::address!("0000000000000000000000000000000000000002"),
|
|
507
|
+
U256::from(6),
|
|
508
|
+
6,
|
|
509
|
+
),
|
|
510
|
+
] {
|
|
511
|
+
let account = history
|
|
512
|
+
.get_by_block_and_address(&mut txn, history_db, block_number, &address)
|
|
513
|
+
.unwrap();
|
|
514
|
+
|
|
515
|
+
assert!(account.0.is_some_and(|a| a
|
|
516
|
+
== HistoricalAccountData {
|
|
517
|
+
balance: balance,
|
|
518
|
+
nonce: nonce,
|
|
519
|
+
code_hash: revm::primitives::KECCAK_EMPTY,
|
|
520
|
+
}));
|
|
521
|
+
assert!(account.1 == false);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Write empty blocks until everything is evicted
|
|
525
|
+
for i in 5..10 {
|
|
526
|
+
// Block 1
|
|
527
|
+
history
|
|
528
|
+
.insert(&mut txn, history_db, i as u64, vec![])
|
|
529
|
+
.unwrap();
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// Assert no accounts in history left
|
|
533
|
+
for i in 0..10 {
|
|
534
|
+
for address in vec![
|
|
535
|
+
revm::primitives::address!("0000000000000000000000000000000000000001"),
|
|
536
|
+
revm::primitives::address!("0000000000000000000000000000000000000002"),
|
|
537
|
+
] {
|
|
538
|
+
let account = history
|
|
539
|
+
.get_by_block_and_address(&mut txn, history_db, i, &address)
|
|
540
|
+
.unwrap();
|
|
541
|
+
assert_eq!(account, (None, i >= 10 - history.capacity));
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
use alloy_primitives::wrap_fixed_bytes;
|
|
2
|
+
use bs58;
|
|
3
|
+
use revm::primitives::{Address, B256, U256};
|
|
4
|
+
use serde::{Deserialize, Serialize};
|
|
5
|
+
use sha2::{Digest, Sha256};
|
|
6
|
+
|
|
7
|
+
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
|
|
8
|
+
pub struct LegacyColdWallet {
|
|
9
|
+
pub address: LegacyAddress,
|
|
10
|
+
pub balance: U256,
|
|
11
|
+
pub legacy_attributes: LegacyAccountAttributes,
|
|
12
|
+
pub merge_info: Option<(B256, Address)>,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
|
|
16
|
+
pub struct LegacyAccountAttributes {
|
|
17
|
+
pub legacy_nonce: Option<u64>,
|
|
18
|
+
pub second_public_key: Option<String>,
|
|
19
|
+
pub multi_signature: Option<LegacyMultiSignatureAttribute>,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
impl LegacyAccountAttributes {
|
|
23
|
+
pub fn is_empty(&self) -> bool {
|
|
24
|
+
self.second_public_key.is_none() && self.multi_signature.is_none()
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
|
|
29
|
+
pub struct LegacyMultiSignatureAttribute {
|
|
30
|
+
pub min: usize,
|
|
31
|
+
pub public_keys: Vec<String>,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
|
35
|
+
pub enum LegacyAddressError {
|
|
36
|
+
InvalidSize,
|
|
37
|
+
InvalidBase58,
|
|
38
|
+
InvalidChecksum,
|
|
39
|
+
InvalidBytes,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
wrap_fixed_bytes!(
|
|
43
|
+
extra_derives: [],
|
|
44
|
+
// A legacy 21-byte ARK address
|
|
45
|
+
pub struct LegacyAddress<21>;
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
impl std::fmt::Display for LegacyAddress {
|
|
49
|
+
#[inline]
|
|
50
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
51
|
+
let checksum = encode_base58check(&self[..]);
|
|
52
|
+
f.write_str(&checksum)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
impl TryFrom<&str> for LegacyAddress {
|
|
57
|
+
type Error = LegacyAddressError;
|
|
58
|
+
|
|
59
|
+
#[inline]
|
|
60
|
+
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
|
61
|
+
let decoded = decode_base58check(value)?;
|
|
62
|
+
Self::try_from(&decoded[..]).map_err(|_| LegacyAddressError::InvalidBytes)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#[inline]
|
|
67
|
+
fn decode_base58check(encoded: &str) -> Result<Vec<u8>, LegacyAddressError> {
|
|
68
|
+
let decoded = bs58::decode(encoded)
|
|
69
|
+
.into_vec()
|
|
70
|
+
.map_err(|e| e.to_string())
|
|
71
|
+
.map_err(|_| LegacyAddressError::InvalidBase58)?;
|
|
72
|
+
|
|
73
|
+
if decoded.len() < 4 {
|
|
74
|
+
return Err(LegacyAddressError::InvalidSize);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let (data, checksum) = decoded.split_at(decoded.len() - 4);
|
|
78
|
+
let computed_checksum = Sha256::digest(&Sha256::digest(data));
|
|
79
|
+
if &computed_checksum[..4] != checksum {
|
|
80
|
+
return Err(LegacyAddressError::InvalidChecksum);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
Ok(data.to_vec())
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
#[inline]
|
|
87
|
+
fn encode_base58check(data: &[u8]) -> String {
|
|
88
|
+
let checksum = Sha256::digest(&Sha256::digest(data));
|
|
89
|
+
let mut extended_data = data.to_vec();
|
|
90
|
+
extended_data.extend_from_slice(&checksum[..4]);
|
|
91
|
+
|
|
92
|
+
bs58::encode(extended_data).into_string()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
#[cfg(test)]
|
|
96
|
+
mod tests {
|
|
97
|
+
use crate::legacy::{
|
|
98
|
+
LegacyAddress, LegacyAddressError, decode_base58check, encode_base58check,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
#[test]
|
|
102
|
+
fn test_encode() {
|
|
103
|
+
let address = "DJmvhhiQFSrEQCq9FUxvcLcpcBjx7K3yLt";
|
|
104
|
+
|
|
105
|
+
let decoded: [u8; 21] = [
|
|
106
|
+
30, 149, 144, 208, 106, 80, 8, 63, 148, 59, 207, 233, 127, 161, 7, 27, 208, 185, 40,
|
|
107
|
+
87, 19,
|
|
108
|
+
];
|
|
109
|
+
|
|
110
|
+
let actual = encode_base58check(&decoded);
|
|
111
|
+
assert_eq!(actual, address);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
#[test]
|
|
115
|
+
fn test_decode() {
|
|
116
|
+
let address = "DJmvhhiQFSrEQCq9FUxvcLcpcBjx7K3yLt";
|
|
117
|
+
|
|
118
|
+
let decoded: [u8; 21] = [
|
|
119
|
+
30, 149, 144, 208, 106, 80, 8, 63, 148, 59, 207, 233, 127, 161, 7, 27, 208, 185, 40,
|
|
120
|
+
87, 19,
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
let actual = decode_base58check(address).expect("ok");
|
|
124
|
+
assert_eq!(actual, decoded);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
#[test]
|
|
128
|
+
fn test_from_str() {
|
|
129
|
+
let address: LegacyAddress = "DJmvhhiQFSrEQCq9FUxvcLcpcBjx7K3yLt".try_into().expect("ok");
|
|
130
|
+
|
|
131
|
+
let decoded: [u8; 21] = [
|
|
132
|
+
30, 149, 144, 208, 106, 80, 8, 63, 148, 59, 207, 233, 127, 161, 7, 27, 208, 185, 40,
|
|
133
|
+
87, 19,
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
assert_eq!(&address[..], decoded);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
#[test]
|
|
140
|
+
fn test_decode_failure() {
|
|
141
|
+
let address = "_!@@@";
|
|
142
|
+
let err = decode_base58check(address).expect_err("must err");
|
|
143
|
+
assert_eq!(err, LegacyAddressError::InvalidBase58);
|
|
144
|
+
|
|
145
|
+
let address = "DJm";
|
|
146
|
+
let err = decode_base58check(address).expect_err("must err");
|
|
147
|
+
assert_eq!(err, LegacyAddressError::InvalidSize);
|
|
148
|
+
|
|
149
|
+
let address = "DjmvhhiqfSrEQCq9FUxvcLcpcBjx7K3yLt";
|
|
150
|
+
let err = decode_base58check(address).expect_err("must err");
|
|
151
|
+
assert_eq!(err, LegacyAddressError::InvalidChecksum);
|
|
152
|
+
}
|
|
153
|
+
}
|