Skip to content
This repository was archived by the owner on Nov 6, 2022. It is now read-only.

Commit 6036090

Browse files
asm check
1 parent 456e578 commit 6036090

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+2247
-927
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,6 @@ petgraph = "0.6.0"
4343

4444
[features]
4545
sparse_buffers = []
46+
47+
[profile.release]
48+
debug = true

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
generics_files = basic simple nested func closure colorful queue
77
generics_outputs = $(patsubst %,generics/%, $(generics_files))
88

9-
minitest_outputs = arithmetic codeloadtest globaltest simple-closure closure quick wide-tuples $(generics_outputs)
9+
minitest_outputs = arithmetic codeloadtest globaltest simple-closure closure stack-safety quick wide-tuples $(generics_outputs)
1010
upgrade_outputs = regcopy_new regcopy_old upgrade1_new upgrade1_old
1111
looptest_outputs = upgrade2_new upgrade2_old
1212
builtin_outputs = arraytest kvstest maptest

arb_os/accounts.mini

Lines changed: 88 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use std::storageMap::storageMap_new;
1818
use std::storageMap::storageMap_size;
1919
use std::storageMap::storageMap_get;
2020
use std::storageMap::storageMap_set;
21+
use std::storageMap::storageMap_forall;
2122

2223
use core::kvs::Kvs;
2324
use core::kvs::builtin_kvsSize;
@@ -70,7 +71,9 @@ type Account = struct {
7071
};
7172

7273
type AccountContractInfo = struct {
73-
code: ByteArray, // deployed EVM code for the contract
74+
contractStateVersion: uint, // this changes when the rules of contract interpretation change,
75+
// for example due to Ethereum hardfork
76+
code: ByteArray, // deployed EVM code for the contract
7477
evmJumpTable: map<uint, view write func()>, // maps each valid EVM jump destination to the corresponding AVM codepoint
7578
startCodePoint: view write func(), // entry point for the translated AVM code
7679
storage: StorageMap,
@@ -140,7 +143,7 @@ public write func setGlobalAccountStore(acctStore: AccountStore) {
140143
}
141144

142145
public func accountStore_get(acctStore: AccountStore, addr: address) -> Account {
143-
return xif let Some(acct) = acctStore.accounts[addr] {
146+
return if let Some(acct) = acctStore.accounts[addr] {
144147
acct
145148
} else {
146149
// There is no recorded account at this address, so make a pristine account.
@@ -194,8 +197,11 @@ public func accountStore_destroyAccount(acctStore: AccountStore, addrToDestroy:
194197
if let Some(contractInfo) = accountStore_get(acctStore, addrToDestroy).contractInfo {
195198
acctStore = accountStore_dropCodeRef(
196199
acctStore,
197-
keccak256(contractInfo.code, 0, bytearray_size(contractInfo.code))
200+
hashForCodeRef(contractInfo.code, contractInfo.contractStateVersion),
198201
);
202+
if (acctStore.numContracts > 0) { // avoid underflow, if the count is somehow incorrect
203+
set acctStore.numContracts = acctStore.numContracts-1;
204+
}
199205
}
200206
return accountStore_set(acctStore, addrToDestroy, pristineAccount(addrToDestroy));
201207
}
@@ -215,7 +221,7 @@ public func account_checkAndIncrSeqNum(
215221
// if seqNumRecvd has the expected value, increment seqNum in account and return updated account.
216222
// else return None
217223
let nextSeq = account.nextSeqNum;
218-
return xif (nextSeq == seqNumRecvd) {
224+
return if (nextSeq == seqNumRecvd) {
219225
Some(account with { nextSeqNum: nextSeq+1 })
220226
} else {
221227
None<Account>
@@ -239,7 +245,7 @@ public func account_getAggregatorToPayAsOption(account: Account) -> option<addre
239245
}
240246

241247
public view func account_getAggregatorToPay(account: Account) -> address {
242-
return xif let Some(atp) = account.aggregatorToPay {
248+
return if let Some(atp) = account.aggregatorToPay {
243249
atp
244250
} else {
245251
chainParams_getDefaultAggregator()
@@ -293,7 +299,7 @@ public view func account_setAggregatorDecompressionState(
293299
) -> Account {
294300
return account with {
295301
aggregatorInfo: Some(
296-
xif let Some(aggInfo) = account.aggregatorInfo {
302+
if let Some(aggInfo) = account.aggregatorInfo {
297303
aggInfo with {
298304
decompressionState: maybeState
299305
}
@@ -313,7 +319,7 @@ public func _accountStore_feeCollectorForAggregator(acctStore: AccountStore, agg
313319
}
314320

315321
public func account_getFeeCollector(account: Account) -> address {
316-
return xif let Some(aggInfo) = account.aggregatorInfo {
322+
return if let Some(aggInfo) = account.aggregatorInfo {
317323
aggInfo.feeCollector
318324
} else {
319325
account.addr // if fee collector isn't explicitly set, fees go to the account's own address
@@ -323,7 +329,7 @@ public func account_getFeeCollector(account: Account) -> address {
323329
public view func account_setFeeCollector(account: Account, newCollector: address) -> Account {
324330
return account with {
325331
aggregatorInfo: Some(
326-
xif let Some(aggInfo) = account.aggregatorInfo {
332+
if let Some(aggInfo) = account.aggregatorInfo {
327333
aggInfo with {
328334
feeCollector: newCollector
329335
}
@@ -341,7 +347,7 @@ public view func account_setFeeCollector(account: Account, newCollector: address
341347
public func account_setBaseTxFeeL1Gas(account: Account, fee: uint) -> Account {
342348
return account with {
343349
aggregatorInfo: Some(
344-
xif let Some(aggInfo) = account.aggregatorInfo {
350+
if let Some(aggInfo) = account.aggregatorInfo {
345351
aggInfo with {
346352
baseTxFeeL1Gas: fee
347353
}
@@ -367,14 +373,15 @@ public view write func accountStore_createAccountFromEvmCode(
367373
// Create a new account for a compiled EVM contract.
368374
// Returns Some(updatedAccountStore), or None if something went wrong.
369375
let oldAcct = accountStore_get(store, newAddr);
370-
return xif ( ! account_hasContract(oldAcct)) {
376+
return if ( ! account_hasContract(oldAcct)) {
371377
evmCallStack_addStorageCharge( (bytearray_size(code) + 31) / 32 );
372378
set oldAcct.nextSeqNum = 1;
373379
set oldAcct.contractInfo = Some(struct {
374-
code: code,
375-
evmJumpTable: evmJumpTable,
376-
startCodePoint: initCodePt,
377-
storage: storageMap,
380+
contractStateVersion: const::ContractStateVersion_current,
381+
code: code,
382+
evmJumpTable: evmJumpTable,
383+
startCodePoint: initCodePt,
384+
storage: storageMap,
378385
});
379386
Some(accountStore_set(store, newAddr, oldAcct))
380387
} else {
@@ -394,18 +401,19 @@ public func accountStore_upgradeContractFromEvmCode(
394401
let oldAcct = accountStore_get(store, addr);
395402
let contractAdded = false;
396403
set oldAcct.contractInfo = Some(struct {
404+
contractStateVersion: const::ContractStateVersion_current,
397405
code: code,
398406
evmJumpTable: evmJumpTable,
399407
startCodePoint: initCodePt,
400-
storage: xif let Some(cinfo) = oldAcct.contractInfo {
408+
storage: if let Some(cinfo) = oldAcct.contractInfo {
401409
cinfo.storage
402410
} else {
403411
contractAdded = true;
404412
storageMap_new()
405413
},
406414
});
407415
store = accountStore_set(store, addr, oldAcct);
408-
return xif (contractAdded) {
416+
return if (contractAdded) {
409417
accountStore_changeNumContracts(store, int(1))
410418
} else {
411419
store
@@ -430,12 +438,13 @@ public func accountStore_createBuiltinContract(
430438
fakeCode = bytearray_setByte(fakeCode, 0, 0xfe);
431439
}
432440

433-
return xif (account_isEmpty(oldAcct) || !isUpgrade) {
441+
return if (account_isEmpty(oldAcct) || !isUpgrade) {
434442
set oldAcct.contractInfo = Some(struct {
443+
contractStateVersion: const::ContractStateVersion_current,
435444
code: fakeCode,
436445
evmJumpTable: newmap<uint, view write func()>,
437446
startCodePoint: entryPoint,
438-
storage: xif (isUpgrade && (oldAcct.contractInfo != None<AccountContractInfo>)) {
447+
storage: if (isUpgrade && (oldAcct.contractInfo != None<AccountContractInfo>)) {
439448
(oldAcct.contractInfo?).storage
440449
} else {
441450
storageMap_new()
@@ -453,7 +462,7 @@ public func accountStore_createBuiltinContract(
453462
numContracts: acctStore.numContracts + 1
454463
}
455464
)
456-
} elseif (isUpgrade) {
465+
} else if (isUpgrade) {
457466
Some(accountStore_upgradeContractFromEvmCode(
458467
acctStore,
459468
addr,
@@ -476,7 +485,7 @@ public func account_addToEthBalance(account: Account, addition: uint) -> Account
476485
}
477486

478487
public func account_deductFromEthBalance(account: Account, deduction: uint) -> option<Account> {
479-
return xif (account.ethBalance >= deduction) {
488+
return if (account.ethBalance >= deduction) {
480489
Some(
481490
account with { ethBalance: account.ethBalance-deduction }
482491
)
@@ -508,35 +517,55 @@ public func accountStore_transferEthBalance(
508517
// Allocate a new escrow box, and transfer amount into it from the account of payer
509518
// Return None if payer has insufficient funds
510519
public func accountStore_newEscrow(acctStore: AccountStore, payer: address, amount: uint) -> option<(AccountStore, uint)> {
511-
return xif (amount == 0) {
512-
Some((acctStore, const::EscrowStoreID_txGas))
520+
let key = acctStore.escrowStore.nextKey;
521+
let updatedEscrowedValues = if (amount == 0) {
522+
// in this case we're allocating a new escrow box, which holds zero funds
523+
// this is not a waste of space in escrowedValues because a zero value doesn't consume space in a StorageMap
524+
acctStore.escrowStore.escrowedValues
513525
} else {
514526
acctStore = accountStore_set(
515527
acctStore,
516528
payer,
517529
account_deductFromEthBalance(accountStore_get(acctStore, payer), amount)?,
518530
);
519-
let key = acctStore.escrowStore.nextKey;
520-
Some((
521-
acctStore with {
522-
escrowStore: struct {
523-
nextKey: key + 1,
524-
escrowedValues: storageMap_set(acctStore.escrowStore.escrowedValues, key, amount),
525-
}
526-
},
527-
key
528-
))
531+
storageMap_set(acctStore.escrowStore.escrowedValues, key, amount)
529532
};
533+
return Some((
534+
acctStore with {
535+
escrowStore: struct {
536+
nextKey: key + 1,
537+
escrowedValues: updatedEscrowedValues,
538+
}
539+
},
540+
key
541+
));
530542
}
531543

532-
public func _accountStore_getEscrowBalance(acctStore: AccountStore, key: uint) -> uint {
544+
public func accountStore_getEscrowBalance(acctStore: AccountStore, key: uint) -> uint {
533545
return storageMap_get(acctStore.escrowStore.escrowedValues, key);
534546
}
535547

548+
public func accountStore_sumOfAllEscrowBalances(acctStore: AccountStore) -> uint {
549+
unsafecast<uint>(
550+
storageMap_forall(
551+
acctStore.escrowStore.escrowedValues,
552+
/*closure(_k: uint, v: uint, state: any) -> any {
553+
return unsafecast<uint>(state) + v;
554+
},*/
555+
test_func,
556+
0,
557+
)
558+
)
559+
}
560+
561+
public func test_func(k: uint, v: uint, state: any) -> any {
562+
unsafecast<uint>(state) + v
563+
}
564+
536565
// Transfer funds into an existing escrow box
537566
public func _accountStore_addToEscrow(acctStore: AccountStore, key: uint, payer: address, amount: uint) -> option<AccountStore> {
538567
let acct = accountStore_get(acctStore, payer);
539-
return xif (acct.ethBalance < amount) {
568+
return if (acct.ethBalance < amount) {
540569
None<AccountStore>
541570
} else {
542571
let oldValue = storageMap_get(acctStore.escrowStore.escrowedValues, key);
@@ -554,7 +583,7 @@ public func _accountStore_addToEscrow(acctStore: AccountStore, key: uint, payer:
554583
public func accountStore_addToEscrowUpToMax(acctStore: AccountStore, key: uint, payer: address, maxAmount: uint) -> (AccountStore, uint) {
555584
let acct = accountStore_get(acctStore, payer);
556585
let balance = account_getEthBalance(acct);
557-
let amount = xif (balance < maxAmount) { balance } else { maxAmount };
586+
let amount = if (balance < maxAmount) { balance } else { maxAmount };
558587
let oldValue = storageMap_get(acctStore.escrowStore.escrowedValues, key);
559588
return (
560589
accountStore_set(acctStore, payer, acct with { ethBalance: acct.ethBalance-amount }) with {
@@ -569,7 +598,7 @@ public func accountStore_addToEscrowUpToMax(acctStore: AccountStore, key: uint,
569598
// Transfer funds out of an escrow box into an account, or return None if box has insufficient funds.
570599
public func accountStore_payFromEscrow(acctStore: AccountStore, key: uint, recipient: address, amount: uint) -> option<AccountStore> {
571600
let oldEscrow = storageMap_get(acctStore.escrowStore.escrowedValues, key);
572-
return xif (oldEscrow < amount) {
601+
return if (oldEscrow < amount) {
573602
None<AccountStore>
574603
} else {
575604
let oldAcct = accountStore_get(acctStore, recipient);
@@ -648,6 +677,7 @@ public func account_setContractInfo(
648677

649678
return acct with { contractInfo: Some(
650679
struct {
680+
contractStateVersion: const::ContractStateVersion_current,
651681
code: code,
652682
evmJumpTable: evmJumpTable,
653683
startCodePoint: startCodePoint,
@@ -657,7 +687,7 @@ public func account_setContractInfo(
657687
}
658688

659689
public func account_getCodeSize(acct: Account) -> uint {
660-
return xif let Some(contractInfo) = acct.contractInfo {
690+
return if let Some(contractInfo) = acct.contractInfo {
661691
bytearray_size(contractInfo.code)
662692
} else {
663693
0 // Account has no code, so its codesize is deemed to be zero.
@@ -668,6 +698,14 @@ public func account_getCode(acct: Account) -> option<ByteArray> {
668698
return Some((acct.contractInfo?).code);
669699
}
670700

701+
public func account_usesOriginalStorageGasAlloc(acct: Account) -> bool {
702+
return if let Some(contractInfo) = acct.contractInfo {
703+
contractInfo.contractStateVersion == const::ContractStateVersion_original
704+
} else {
705+
false
706+
};
707+
}
708+
671709
type asfa_wrappedState = struct {
672710
innerClosure: func(Account, any) -> any,
673711
innerState: any,
@@ -696,20 +734,28 @@ func asfaClosure(_: any, acct: Account, wrappedState: asfa_wrappedState) -> asfa
696734
};
697735
}
698736

737+
func hashForCodeRef(code: ByteArray, contractStateVersion: uint) -> bytes32 {
738+
// This hash, meant as the key in the coderef table, is a collision-free function of this function's args.
739+
// For the original contractStateVersion (= 0) this is just the keccak256 of the code, so it is
740+
// backward-compatible with the original hashing scheme.
741+
return bytes32(uint(keccak256(code, 0, bytearray_size(code))) + contractStateVersion); // overflow OK
742+
}
743+
699744
// If a CodeRef exists for code, increment its reference count.
700745
// If one doesn't exist, create and initialize one.
701746
// Return the attributes of the resulting CodeRef
702747
public view write func accountStore_createOrAddCodeRef(
703748
acctStore: AccountStore,
749+
contractStateVersion: uint,
704750
code: ByteArray
705751
) -> option<(
706752
AccountStore,
707753
view write func(),
708754
map<uint, view write func()>,
709755
bool,
710756
)> {
711-
let codeHash = keccak256(code, 0, bytearray_size(code));
712-
return xif let Some(codeRef) = acctStore.codeRefTable[codeHash] {
757+
let codeHash = hashForCodeRef(code, contractStateVersion); // overflow OK
758+
return if let Some(codeRef) = acctStore.codeRefTable[codeHash] {
713759
Some((
714760
accountStore_addCodeRef(acctStore, codeHash)?,
715761
codeRef.startCodePoint,
@@ -719,7 +765,7 @@ public view write func accountStore_createOrAddCodeRef(
719765
} else {
720766
let (startCodePoint, evmJumpTable, _) = translateEvmCodeSegment(bytestream_new(code), false);
721767
Some((
722-
accountStore_createCodeRef(acctStore, code, evmJumpTable, startCodePoint),
768+
accountStore_createCodeRef(acctStore, contractStateVersion, code, evmJumpTable, startCodePoint),
723769
unsafecast<view write func()>(startCodePoint),
724770
unsafecast<map<uint, view write func()> >(evmJumpTable),
725771
true,
@@ -738,11 +784,12 @@ public func accountStore_addCodeRef(acctStore: AccountStore, codeHash: bytes32)
738784

739785
public func accountStore_createCodeRef(
740786
acctStore: AccountStore,
787+
contractStateVersion: uint,
741788
code: ByteArray,
742789
evmJumpTable: map<uint, view write func()>,
743790
startCodePoint: view write func(),
744791
) -> AccountStore {
745-
let codeHash = keccak256(code, 0, bytearray_size(code));
792+
let codeHash = hashForCodeRef(code, contractStateVersion); // overflow OK
746793
set acctStore.codeRefTable[codeHash] = struct {
747794
refCount: 1,
748795
code: code,

0 commit comments

Comments
 (0)