Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
60129ad5
Unverified
Commit
60129ad5
authored
Mar 16, 2023
by
mergify[bot]
Committed by
GitHub
Mar 16, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5151 from ethereum-optimism/feat/parallel-migration
op-chain-ops: Add parallel migration
parents
025de3de
47dada2d
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
786 additions
and
110 deletions
+786
-110
main.go
op-chain-ops/cmd/check-migration/main.go
+210
-0
main.go
op-chain-ops/cmd/op-migrate/main.go
+5
-0
cli.go
op-chain-ops/ether/cli.go
+2
-2
migrate.go
op-chain-ops/ether/migrate.go
+6
-17
precheck.go
op-chain-ops/ether/precheck.go
+244
-78
precheck_test.go
op-chain-ops/ether/precheck_test.go
+295
-0
check.go
op-chain-ops/genesis/check.go
+5
-3
db_migration.go
op-chain-ops/genesis/db_migration.go
+19
-10
No files found.
op-chain-ops/cmd/check-migration/main.go
0 → 100644
View file @
60129ad5
package
main
import
(
"context"
"fmt"
"math/big"
"os"
"strings"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum-optimism/optimism/op-chain-ops/db"
"github.com/mattn/go-isatty"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-bindings/hardhat"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/urfave/cli"
)
func
main
()
{
log
.
Root
()
.
SetHandler
(
log
.
StreamHandler
(
os
.
Stderr
,
log
.
TerminalFormat
(
isatty
.
IsTerminal
(
os
.
Stderr
.
Fd
()))))
app
:=
&
cli
.
App
{
Name
:
"check-migration"
,
Usage
:
"Run sanity checks on a migrated database"
,
Flags
:
[]
cli
.
Flag
{
&
cli
.
StringFlag
{
Name
:
"l1-rpc-url"
,
Value
:
"http://127.0.0.1:8545"
,
Usage
:
"RPC URL for an L1 Node"
,
Required
:
true
,
},
&
cli
.
StringFlag
{
Name
:
"ovm-addresses"
,
Usage
:
"Path to ovm-addresses.json"
,
Required
:
true
,
},
&
cli
.
StringFlag
{
Name
:
"ovm-allowances"
,
Usage
:
"Path to ovm-allowances.json"
,
Required
:
true
,
},
&
cli
.
StringFlag
{
Name
:
"ovm-messages"
,
Usage
:
"Path to ovm-messages.json"
,
Required
:
true
,
},
&
cli
.
StringFlag
{
Name
:
"witness-file"
,
Usage
:
"Path to witness file"
,
Required
:
true
,
},
&
cli
.
StringFlag
{
Name
:
"db-path"
,
Usage
:
"Path to database"
,
Required
:
true
,
},
cli
.
StringFlag
{
Name
:
"deploy-config"
,
Usage
:
"Path to hardhat deploy config file"
,
Required
:
true
,
},
cli
.
StringFlag
{
Name
:
"network"
,
Usage
:
"Name of hardhat deploy network"
,
Required
:
true
,
},
cli
.
StringFlag
{
Name
:
"hardhat-deployments"
,
Usage
:
"Comma separated list of hardhat deployment directories"
,
Required
:
true
,
},
cli
.
IntFlag
{
Name
:
"db-cache"
,
Usage
:
"LevelDB cache size in mb"
,
Value
:
1024
,
},
cli
.
IntFlag
{
Name
:
"db-handles"
,
Usage
:
"LevelDB number of handles"
,
Value
:
60
,
},
},
Action
:
func
(
ctx
*
cli
.
Context
)
error
{
deployConfig
:=
ctx
.
String
(
"deploy-config"
)
config
,
err
:=
genesis
.
NewDeployConfig
(
deployConfig
)
if
err
!=
nil
{
return
err
}
ovmAddresses
,
err
:=
crossdomain
.
NewAddresses
(
ctx
.
String
(
"ovm-addresses"
))
if
err
!=
nil
{
return
err
}
ovmAllowances
,
err
:=
crossdomain
.
NewAllowances
(
ctx
.
String
(
"ovm-allowances"
))
if
err
!=
nil
{
return
err
}
ovmMessages
,
err
:=
crossdomain
.
NewSentMessageFromJSON
(
ctx
.
String
(
"ovm-messages"
))
if
err
!=
nil
{
return
err
}
evmMessages
,
evmAddresses
,
err
:=
crossdomain
.
ReadWitnessData
(
ctx
.
String
(
"witness-file"
))
if
err
!=
nil
{
return
err
}
log
.
Info
(
"Loaded witness data"
,
"ovmAddresses"
,
len
(
ovmAddresses
),
"evmAddresses"
,
len
(
evmAddresses
),
"ovmAllowances"
,
len
(
ovmAllowances
),
"ovmMessages"
,
len
(
ovmMessages
),
"evmMessages"
,
len
(
evmMessages
),
)
migrationData
:=
crossdomain
.
MigrationData
{
OvmAddresses
:
ovmAddresses
,
EvmAddresses
:
evmAddresses
,
OvmAllowances
:
ovmAllowances
,
OvmMessages
:
ovmMessages
,
EvmMessages
:
evmMessages
,
}
network
:=
ctx
.
String
(
"network"
)
deployments
:=
strings
.
Split
(
ctx
.
String
(
"hardhat-deployments"
),
","
)
hh
,
err
:=
hardhat
.
New
(
network
,
[]
string
{},
deployments
)
if
err
!=
nil
{
return
err
}
l1RpcURL
:=
ctx
.
String
(
"l1-rpc-url"
)
l1Client
,
err
:=
ethclient
.
Dial
(
l1RpcURL
)
if
err
!=
nil
{
return
err
}
var
block
*
types
.
Block
tag
:=
config
.
L1StartingBlockTag
if
tag
.
BlockNumber
!=
nil
{
block
,
err
=
l1Client
.
BlockByNumber
(
context
.
Background
(),
big
.
NewInt
(
tag
.
BlockNumber
.
Int64
()))
}
else
if
tag
.
BlockHash
!=
nil
{
block
,
err
=
l1Client
.
BlockByHash
(
context
.
Background
(),
*
tag
.
BlockHash
)
}
else
{
return
fmt
.
Errorf
(
"invalid l1StartingBlockTag in deploy config: %v"
,
tag
)
}
if
err
!=
nil
{
return
err
}
dbCache
:=
ctx
.
Int
(
"db-cache"
)
dbHandles
:=
ctx
.
Int
(
"db-handles"
)
// Read the required deployment addresses from disk if required
if
err
:=
config
.
GetDeployedAddresses
(
hh
);
err
!=
nil
{
return
err
}
if
err
:=
config
.
Check
();
err
!=
nil
{
return
err
}
postLDB
,
err
:=
db
.
Open
(
ctx
.
String
(
"db-path"
),
dbCache
,
dbHandles
)
if
err
!=
nil
{
return
err
}
if
err
:=
genesis
.
PostCheckMigratedDB
(
postLDB
,
migrationData
,
&
config
.
L1CrossDomainMessengerProxy
,
config
.
L1ChainID
,
config
.
FinalSystemOwner
,
config
.
ProxyAdminOwner
,
&
derive
.
L1BlockInfo
{
Number
:
block
.
NumberU64
(),
Time
:
block
.
Time
(),
BaseFee
:
block
.
BaseFee
(),
BlockHash
:
block
.
Hash
(),
BatcherAddr
:
config
.
BatchSenderAddress
,
L1FeeOverhead
:
eth
.
Bytes32
(
common
.
BigToHash
(
new
(
big
.
Int
)
.
SetUint64
(
config
.
GasPriceOracleOverhead
))),
L1FeeScalar
:
eth
.
Bytes32
(
common
.
BigToHash
(
new
(
big
.
Int
)
.
SetUint64
(
config
.
GasPriceOracleScalar
))),
},
);
err
!=
nil
{
return
err
}
if
err
:=
postLDB
.
Close
();
err
!=
nil
{
return
err
}
return
nil
},
}
if
err
:=
app
.
Run
(
os
.
Args
);
err
!=
nil
{
log
.
Crit
(
"error in migration"
,
"err"
,
err
)
}
}
op-chain-ops/cmd/op-migrate/main.go
View file @
60129ad5
...
@@ -106,6 +106,11 @@ func main() {
...
@@ -106,6 +106,11 @@ func main() {
Value
:
"rollup.json"
,
Value
:
"rollup.json"
,
Required
:
true
,
Required
:
true
,
},
},
cli
.
BoolFlag
{
Name
:
"post-check-only"
,
Usage
:
"Only perform sanity checks"
,
Required
:
false
,
},
},
},
Action
:
func
(
ctx
*
cli
.
Context
)
error
{
Action
:
func
(
ctx
*
cli
.
Context
)
error
{
deployConfig
:=
ctx
.
String
(
"deploy-config"
)
deployConfig
:=
ctx
.
String
(
"deploy-config"
)
...
...
op-chain-ops/ether/cli.go
View file @
60129ad5
...
@@ -25,8 +25,8 @@ func GetOVMETHTotalSupplySlot() common.Hash {
...
@@ -25,8 +25,8 @@ func GetOVMETHTotalSupplySlot() common.Hash {
return
getOVMETHTotalSupplySlot
()
return
getOVMETHTotalSupplySlot
()
}
}
//
g
etOVMETHBalance gets a user's OVM ETH balance from state by querying the
//
G
etOVMETHBalance gets a user's OVM ETH balance from state by querying the
// appropriate storage slot directly.
// appropriate storage slot directly.
func
g
etOVMETHBalance
(
db
*
state
.
StateDB
,
addr
common
.
Address
)
*
big
.
Int
{
func
G
etOVMETHBalance
(
db
*
state
.
StateDB
,
addr
common
.
Address
)
*
big
.
Int
{
return
db
.
GetState
(
OVMETHAddress
,
CalcOVMETHStorageKey
(
addr
))
.
Big
()
return
db
.
GetState
(
OVMETHAddress
,
CalcOVMETHStorageKey
(
addr
))
.
Big
()
}
}
op-chain-ops/ether/migrate.go
View file @
60129ad5
...
@@ -29,7 +29,9 @@ var (
...
@@ -29,7 +29,9 @@ var (
}
}
)
)
func
MigrateLegacyETH
(
db
*
state
.
StateDB
,
addresses
[]
common
.
Address
,
chainID
int
,
noCheck
bool
)
error
{
type
FilteredOVMETHAddresses
[]
common
.
Address
func
MigrateLegacyETH
(
db
*
state
.
StateDB
,
addresses
FilteredOVMETHAddresses
,
chainID
int
,
noCheck
bool
)
error
{
// Chain params to use for integrity checking.
// Chain params to use for integrity checking.
params
:=
crossdomain
.
ParamsByChainID
[
chainID
]
params
:=
crossdomain
.
ParamsByChainID
[
chainID
]
if
params
==
nil
{
if
params
==
nil
{
...
@@ -39,28 +41,15 @@ func MigrateLegacyETH(db *state.StateDB, addresses []common.Address, chainID int
...
@@ -39,28 +41,15 @@ func MigrateLegacyETH(db *state.StateDB, addresses []common.Address, chainID int
// Log the chain params for debugging purposes.
// Log the chain params for debugging purposes.
log
.
Info
(
"Chain params"
,
"chain-id"
,
chainID
,
"supply-delta"
,
params
.
ExpectedSupplyDelta
)
log
.
Info
(
"Chain params"
,
"chain-id"
,
chainID
,
"supply-delta"
,
params
.
ExpectedSupplyDelta
)
// Deduplicate the list of addresses by converting to a map.
deduped
:=
make
(
map
[
common
.
Address
]
bool
)
for
_
,
addr
:=
range
addresses
{
deduped
[
addr
]
=
true
}
// Migrate the legacy ETH to ETH.
// Migrate the legacy ETH to ETH.
log
.
Info
(
"Migrating legacy ETH to ETH"
,
"num-accounts"
,
len
(
addresses
))
log
.
Info
(
"Migrating legacy ETH to ETH"
,
"num-accounts"
,
len
(
addresses
))
totalMigrated
:=
new
(
big
.
Int
)
totalMigrated
:=
new
(
big
.
Int
)
logAccountProgress
:=
util
.
ProgressLogger
(
1000
,
"imported accounts"
)
logAccountProgress
:=
util
.
ProgressLogger
(
1000
,
"imported accounts"
)
for
addr
:=
range
deduped
{
for
_
,
addr
:=
range
addresses
{
// No accounts should have a balance in state. If they do, bail.
// Balances are pre-checked not have any balances in state.
if
db
.
GetBalance
(
addr
)
.
Sign
()
>
0
{
if
noCheck
{
log
.
Error
(
"account has non-zero balance in state - should never happen"
,
"addr"
,
addr
)
}
else
{
log
.
Crit
(
"account has non-zero balance in state - should never happen"
,
"addr"
,
addr
)
}
}
// Pull out the OVM ETH balance.
// Pull out the OVM ETH balance.
ovmBalance
:=
g
etOVMETHBalance
(
db
,
addr
)
ovmBalance
:=
G
etOVMETHBalance
(
db
,
addr
)
// Actually perform the migration by setting the appropriate values in state.
// Actually perform the migration by setting the appropriate values in state.
db
.
SetBalance
(
addr
,
ovmBalance
)
db
.
SetBalance
(
addr
,
ovmBalance
)
...
...
op-chain-ops/ether/precheck.go
View file @
60129ad5
package
ether
package
ether
import
(
import
(
"errors"
"fmt"
"fmt"
"math/big"
"math/big"
"sync"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum-optimism/optimism/op-chain-ops/util"
"github.com/ethereum-optimism/optimism/op-chain-ops/util"
...
@@ -11,132 +14,295 @@ import (
...
@@ -11,132 +14,295 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
)
)
const
(
// checkJobs is the number of parallel workers to spawn
// when iterating the storage trie.
checkJobs
=
64
)
// maxSlot is the maximum possible storage slot.
var
maxSlot
=
common
.
HexToHash
(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
)
// accountData is a wrapper struct that contains the balance and address of an account.
// It gets passed via channel to the collector process.
type
accountData
struct
{
balance
*
big
.
Int
address
common
.
Address
}
type
DBFactory
func
()
(
*
state
.
StateDB
,
error
)
// PreCheckBalances checks that the given list of addresses and allowances represents all storage
// PreCheckBalances checks that the given list of addresses and allowances represents all storage
// slots in the LegacyERC20ETH contract. We don't have to filter out extra addresses like we do for
// slots in the LegacyERC20ETH contract. We don't have to filter out extra addresses like we do for
// withdrawals because we'll simply carry the balance of a given address to the new system, if the
// withdrawals because we'll simply carry the balance of a given address to the new system, if the
// account is extra then it won't have any balance and nothing will happen.
// account is extra then it won't have any balance and nothing will happen.
func
PreCheckBalances
(
ldb
ethdb
.
Database
,
db
*
state
.
StateDB
,
addresses
[]
common
.
Address
,
allowances
[]
*
crossdomain
.
Allowance
,
chainID
int
,
noCheck
bool
)
([]
common
.
Addres
s
,
error
)
{
func
PreCheckBalances
(
dbFactory
DBFactory
,
addresses
[]
common
.
Address
,
allowances
[]
*
crossdomain
.
Allowance
,
chainID
int
,
noCheck
bool
)
(
FilteredOVMETHAddresse
s
,
error
)
{
// Chain params to use for integrity checking.
// Chain params to use for integrity checking.
params
:=
crossdomain
.
ParamsByChainID
[
chainID
]
params
:=
crossdomain
.
ParamsByChainID
[
chainID
]
if
params
==
nil
{
if
params
==
nil
{
return
nil
,
fmt
.
Errorf
(
"no chain params for %d"
,
chainID
)
return
nil
,
fmt
.
Errorf
(
"no chain params for %d"
,
chainID
)
}
}
return
doMigration
(
dbFactory
,
addresses
,
allowances
,
params
.
ExpectedSupplyDelta
,
noCheck
)
}
func
doMigration
(
dbFactory
DBFactory
,
addresses
[]
common
.
Address
,
allowances
[]
*
crossdomain
.
Allowance
,
expDiff
*
big
.
Int
,
noCheck
bool
)
(
FilteredOVMETHAddresses
,
error
)
{
// We'll need to maintain a list of all addresses that we've seen along with all of the storage
// We'll need to maintain a list of all addresses that we've seen along with all of the storage
// slots based on the witness data.
// slots based on the witness data.
addrs
:=
make
([]
common
.
Address
,
0
)
addrs
:=
make
([]
common
.
Address
,
0
)
slotsAddrs
:=
make
(
map
[
common
.
Hash
]
common
.
Address
)
slotsInp
:=
make
(
map
[
common
.
Hash
]
int
)
slotsInp
:=
make
(
map
[
common
.
Hash
]
int
)
// For each known address, compute its balance key and add it to the list of addresses.
// For each known address, compute its balance key and add it to the list of addresses.
// Mint events are instrumented as regular ETH events in the witness data, so we no longer
// Mint events are instrumented as regular ETH events in the witness data, so we no longer
// need to iterate over mint events during the migration.
// need to iterate over mint events during the migration.
for
_
,
addr
:=
range
addresses
{
for
_
,
addr
:=
range
addresses
{
addrs
=
append
(
addrs
,
addr
)
sk
:=
CalcOVMETHStorageKey
(
addr
)
slotsInp
[
CalcOVMETHStorageKey
(
addr
)]
=
1
slotsAddrs
[
sk
]
=
addr
slotsInp
[
sk
]
=
1
}
}
// For each known allowance, compute its storage key and add it to the list of addresses.
// For each known allowance, compute its storage key and add it to the list of addresses.
for
_
,
allowance
:=
range
allowances
{
for
_
,
allowance
:=
range
allowances
{
addrs
=
append
(
addrs
,
allowance
.
From
)
sk
:=
CalcAllowanceStorageKey
(
allowance
.
From
,
allowance
.
To
)
slotsInp
[
CalcAllowanceStorageKey
(
allowance
.
From
,
allowance
.
To
)]
=
2
slotsAddrs
[
sk
]
=
allowance
.
From
slotsInp
[
sk
]
=
2
}
}
// Add the old SequencerEntrypoint because someone sent it ETH a long time ago and it has a
// Add the old SequencerEntrypoint because someone sent it ETH a long time ago and it has a
// balance but none of our instrumentation could easily find it. Special case.
// balance but none of our instrumentation could easily find it. Special case.
sequencerEntrypointAddr
:=
common
.
HexToAddress
(
"0x4200000000000000000000000000000000000005"
)
sequencerEntrypointAddr
:=
common
.
HexToAddress
(
"0x4200000000000000000000000000000000000005"
)
addrs
=
append
(
addrs
,
sequencerEntrypointAddr
)
entrySK
:=
CalcOVMETHStorageKey
(
sequencerEntrypointAddr
)
slotsInp
[
CalcOVMETHStorageKey
(
sequencerEntrypointAddr
)]
=
1
slotsAddrs
[
entrySK
]
=
sequencerEntrypointAddr
slotsInp
[
entrySK
]
=
1
// Build a mapping of every storage slot in the LegacyERC20ETH contract, except the list of
// WaitGroup to wait on each iteration job to finish.
// slots that we know we can ignore (totalSupply, name, symbol).
var
wg
sync
.
WaitGroup
var
count
int
// Channel to receive storage slot keys and values from each iteration job.
slotsAct
:=
make
(
map
[
common
.
Hash
]
common
.
Hash
)
outCh
:=
make
(
chan
accountData
)
progress
:=
util
.
ProgressLogger
(
1000
,
"Read OVM_ETH storage slot"
)
// Channel to receive errors from each iteration job.
err
:=
db
.
ForEachStorage
(
predeploys
.
LegacyERC20ETHAddr
,
func
(
key
,
value
common
.
Hash
)
bool
{
errCh
:=
make
(
chan
error
,
checkJobs
)
progress
()
// Channel to cancel all iteration jobs as well as the collector.
cancelCh
:=
make
(
chan
struct
{})
// We can safely ignore specific slots (totalSupply, name, symbol).
// Keep track of the total migrated supply.
if
ignoredSlots
[
key
]
{
totalFound
:=
new
(
big
.
Int
)
return
true
// Divide the key space into partitions by dividing the key space by the number
// of jobs. This will leave some slots left over, which we handle below.
partSize
:=
new
(
big
.
Int
)
.
Div
(
maxSlot
.
Big
(),
big
.
NewInt
(
checkJobs
))
// Define a worker function to iterate over each partition.
worker
:=
func
(
start
,
end
common
.
Hash
)
{
// Decrement the WaitGroup when the function returns.
defer
wg
.
Done
()
db
,
err
:=
dbFactory
()
if
err
!=
nil
{
log
.
Crit
(
"cannot get database"
,
"err"
,
err
)
}
}
// Slot exists, so add it to the map.
// Create a new storage trie. Each trie returned by db.StorageTrie
slotsAct
[
key
]
=
value
// is a copy, so this is safe for concurrent use.
count
++
st
,
err
:=
db
.
StorageTrie
(
predeploys
.
LegacyERC20ETHAddr
)
return
true
})
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot iterate over LegacyERC20ETHAddr: %w"
,
err
)
// Should never happen, so explode if it does.
log
.
Crit
(
"cannot get storage trie for LegacyERC20ETHAddr"
,
"err"
,
err
)
}
if
st
==
nil
{
// Should never happen, so explode if it does.
log
.
Crit
(
"nil storage trie for LegacyERC20ETHAddr"
)
}
}
// Log how many slots were iterated over.
it
:=
trie
.
NewIterator
(
st
.
NodeIterator
(
start
.
Bytes
()))
log
.
Info
(
"Iterated legacy balances"
,
"count"
,
count
)
// Iterate over the list of known slots and check that we have a slot for each one. We'll also
// Below code is largely based on db.ForEachStorage. We can't use that
// keep track of the total balance to be migrated and throw if the total supply exceeds the
// because it doesn't allow us to specify a start and end key.
// expected supply delta.
for
it
.
Next
()
{
totalFound
:=
new
(
big
.
Int
)
select
{
var
unknown
bool
case
<-
cancelCh
:
for
slot
:=
range
slotsAct
{
// If one of the workers encounters an error, cancel all of them.
slotType
,
ok
:=
slotsInp
[
slot
]
return
default
:
break
}
// Use the raw (i.e., secure hashed) key to check if we've reached
// the end of the partition.
if
new
(
big
.
Int
)
.
SetBytes
(
it
.
Key
)
.
Cmp
(
end
.
Big
())
>=
0
{
return
}
// Skip if the value is empty.
rawValue
:=
it
.
Value
if
len
(
rawValue
)
==
0
{
continue
}
// Get the preimage.
key
:=
common
.
BytesToHash
(
st
.
GetKey
(
it
.
Key
))
// Parse the raw value.
_
,
content
,
_
,
err
:=
rlp
.
Split
(
rawValue
)
if
err
!=
nil
{
// Should never happen, so explode if it does.
log
.
Crit
(
"mal-formed data in state: %v"
,
err
)
}
// We can safely ignore specific slots (totalSupply, name, symbol).
if
ignoredSlots
[
key
]
{
continue
}
slotType
,
ok
:=
slotsInp
[
key
]
if
!
ok
{
if
!
ok
{
if
noCheck
{
if
noCheck
{
log
.
Error
(
"ignoring unknown storage slot in state"
,
"slot"
,
slot
.
String
())
log
.
Error
(
"ignoring unknown storage slot in state"
,
"slot"
,
key
.
String
())
}
else
{
}
else
{
unknown
=
true
errCh
<-
fmt
.
Errorf
(
"unknown storage slot in state: %s"
,
key
.
String
())
log
.
Error
(
"unknown storage slot in state"
,
"slot"
,
slot
.
String
())
return
continue
}
}
// No accounts should have a balance in state. If they do, bail.
addr
,
ok
:=
slotsAddrs
[
key
]
if
!
ok
{
log
.
Crit
(
"could not find address in map - should never happen"
)
}
bal
:=
db
.
GetBalance
(
addr
)
if
bal
.
Sign
()
!=
0
{
log
.
Error
(
"account has non-zero balance in state - should never happen"
,
"addr"
,
addr
,
"balance"
,
bal
.
String
(),
)
if
!
noCheck
{
errCh
<-
fmt
.
Errorf
(
"account has non-zero balance in state - should never happen: %s"
,
addr
.
String
())
return
}
}
}
}
// Add balances to the total found.
// Add balances to the total found.
switch
slotType
{
switch
slotType
{
case
1
:
case
1
:
// Balance slot.
// Convert the value to a common.Hash, then send to the channel.
totalFound
.
Add
(
totalFound
,
slotsAct
[
slot
]
.
Big
())
value
:=
common
.
BytesToHash
(
content
)
outCh
<-
accountData
{
balance
:
value
.
Big
(),
address
:
addr
,
}
case
2
:
case
2
:
// Allowance slot.
// Allowance slot.
continue
continue
default
:
default
:
// Should never happen.
// Should never happen.
if
noCheck
{
if
noCheck
{
log
.
Error
(
"unknown slot type"
,
"slot"
,
slot
,
"type"
,
slotType
)
log
.
Error
(
"unknown slot type"
,
"slot"
,
key
,
"type"
,
slotType
)
}
else
{
}
else
{
log
.
Crit
(
"unknown slot type: %d
"
,
slotType
)
log
.
Crit
(
"unknown slot type %d, should never happen
"
,
slotType
)
}
}
}
}
}
}
if
unknown
{
return
nil
,
errors
.
New
(
"unknown storage slots in state (see logs for details)"
)
}
}
for
i
:=
0
;
i
<
checkJobs
;
i
++
{
wg
.
Add
(
1
)
// Compute the start and end keys for this partition.
start
:=
common
.
BigToHash
(
new
(
big
.
Int
)
.
Mul
(
big
.
NewInt
(
int64
(
i
)),
partSize
))
var
end
common
.
Hash
if
i
<
checkJobs
-
1
{
// If this is not the last partition, use the next partition's start key as the end.
end
=
common
.
BigToHash
(
new
(
big
.
Int
)
.
Mul
(
big
.
NewInt
(
int64
(
i
+
1
)),
partSize
))
}
else
{
// If this is the last partition, use the max slot as the end.
end
=
maxSlot
}
// Kick off our worker.
go
worker
(
start
,
end
)
}
// Make a channel to make sure that the collector process completes.
collectorCloseCh
:=
make
(
chan
struct
{})
// Keep track of the last error seen.
var
lastErr
error
// There are multiple ways that the cancel channel can be closed:
// - if we receive an error from the errCh
// - if the collector process completes
// To prevent panics, we wrap the close in a sync.Once.
var
cancelOnce
sync
.
Once
// Kick off another background process to collect
// values from the channel and add them to the map.
var
count
int
progress
:=
util
.
ProgressLogger
(
1000
,
"Collected OVM_ETH storage slot"
)
go
func
()
{
defer
func
()
{
collectorCloseCh
<-
struct
{}{}
}()
for
{
select
{
case
account
:=
<-
outCh
:
progress
()
// Accumulate addresses and total supply.
addrs
=
append
(
addrs
,
account
.
address
)
totalFound
=
new
(
big
.
Int
)
.
Add
(
totalFound
,
account
.
balance
)
case
err
:=
<-
errCh
:
lastErr
=
err
cancelOnce
.
Do
(
func
()
{
close
(
cancelCh
)
})
case
<-
cancelCh
:
return
}
}
}()
// Wait for the workers to finish.
wg
.
Wait
()
// Close the cancel channel to signal the collector process to stop.
cancelOnce
.
Do
(
func
()
{
close
(
cancelCh
)
})
// Wait for the collector process to finish.
<-
collectorCloseCh
// If we saw an error, return it.
if
lastErr
!=
nil
{
return
nil
,
lastErr
}
// Log how many slots were iterated over.
log
.
Info
(
"Iterated legacy balances"
,
"count"
,
count
)
// Verify the supply delta. Recorded total supply in the LegacyERC20ETH contract may be higher
// Verify the supply delta. Recorded total supply in the LegacyERC20ETH contract may be higher
// than the actual migrated amount because self-destructs will remove ETH supply in a way that
// than the actual migrated amount because self-destructs will remove ETH supply in a way that
// cannot be reflected in the contract. This is fine because self-destructs just mean the L2 is
// cannot be reflected in the contract. This is fine because self-destructs just mean the L2 is
// actually *overcollateralized* by some tiny amount.
// actually *overcollateralized* by some tiny amount.
db
,
err
:=
dbFactory
()
if
err
!=
nil
{
log
.
Crit
(
"cannot get database"
,
"err"
,
err
)
}
totalSupply
:=
getOVMETHTotalSupply
(
db
)
totalSupply
:=
getOVMETHTotalSupply
(
db
)
delta
:=
new
(
big
.
Int
)
.
Sub
(
totalSupply
,
totalFound
)
delta
:=
new
(
big
.
Int
)
.
Sub
(
totalSupply
,
totalFound
)
if
delta
.
Cmp
(
params
.
ExpectedSupplyDelta
)
!=
0
{
if
delta
.
Cmp
(
expDiff
)
!=
0
{
if
noCheck
{
log
.
Error
(
log
.
Error
(
"supply mismatch"
,
"supply mismatch"
,
"migrated"
,
totalFound
.
String
(),
"migrated"
,
totalFound
.
String
(),
"supply"
,
totalSupply
.
String
(),
"supply"
,
totalSupply
.
String
(),
"delta"
,
delta
.
String
(),
"delta"
,
delta
.
String
(),
"exp_delta"
,
params
.
ExpectedSupplyDelta
.
String
(),
"exp_delta"
,
expDiff
.
String
(),
)
}
else
{
log
.
Crit
(
"supply mismatch"
,
"migrated"
,
totalFound
.
String
(),
"supply"
,
totalSupply
.
String
(),
"delta"
,
delta
.
String
(),
"exp_delta"
,
params
.
ExpectedSupplyDelta
.
String
(),
)
)
if
!
noCheck
{
return
nil
,
fmt
.
Errorf
(
"supply mismatch: %s"
,
delta
.
String
())
}
}
}
}
...
@@ -146,7 +312,7 @@ func PreCheckBalances(ldb ethdb.Database, db *state.StateDB, addresses []common.
...
@@ -146,7 +312,7 @@ func PreCheckBalances(ldb ethdb.Database, db *state.StateDB, addresses []common.
"migrated"
,
totalFound
.
String
(),
"migrated"
,
totalFound
.
String
(),
"supply"
,
totalSupply
.
String
(),
"supply"
,
totalSupply
.
String
(),
"delta"
,
delta
.
String
(),
"delta"
,
delta
.
String
(),
"exp_delta"
,
params
.
ExpectedSupplyDelta
.
String
(),
"exp_delta"
,
expDiff
.
String
(),
)
)
// We know we have at least a superset of all addresses here since we know that we have every
// We know we have at least a superset of all addresses here since we know that we have every
...
...
op-chain-ops/ether/precheck_test.go
0 → 100644
View file @
60129ad5
package
ether
import
(
"bytes"
"math/big"
"math/rand"
"os"
"sort"
"testing"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/trie"
"github.com/stretchr/testify/require"
)
func
TestPreCheckBalances
(
t
*
testing
.
T
)
{
log
.
Root
()
.
SetHandler
(
log
.
StreamHandler
(
os
.
Stderr
,
log
.
TerminalFormat
(
true
)))
tests
:=
[]
struct
{
name
string
totalSupply
*
big
.
Int
expDiff
*
big
.
Int
stateBalances
map
[
common
.
Address
]
*
big
.
Int
stateAllowances
map
[
common
.
Address
]
common
.
Address
inputAddresses
[]
common
.
Address
inputAllowances
[]
*
crossdomain
.
Allowance
check
func
(
t
*
testing
.
T
,
addrs
FilteredOVMETHAddresses
,
err
error
)
}{
{
name
:
"everything matches"
,
totalSupply
:
big
.
NewInt
(
3
),
expDiff
:
big
.
NewInt
(
0
),
stateBalances
:
map
[
common
.
Address
]
*
big
.
Int
{
common
.
HexToAddress
(
"0x123"
)
:
big
.
NewInt
(
1
),
common
.
HexToAddress
(
"0x456"
)
:
big
.
NewInt
(
2
),
},
stateAllowances
:
map
[
common
.
Address
]
common
.
Address
{
common
.
HexToAddress
(
"0x123"
)
:
common
.
HexToAddress
(
"0x456"
),
},
inputAddresses
:
[]
common
.
Address
{
common
.
HexToAddress
(
"0x123"
),
common
.
HexToAddress
(
"0x456"
),
},
inputAllowances
:
[]
*
crossdomain
.
Allowance
{
{
From
:
common
.
HexToAddress
(
"0x123"
),
To
:
common
.
HexToAddress
(
"0x456"
),
},
},
check
:
func
(
t
*
testing
.
T
,
addrs
FilteredOVMETHAddresses
,
err
error
)
{
require
.
NoError
(
t
,
err
)
require
.
EqualValues
(
t
,
FilteredOVMETHAddresses
{
common
.
HexToAddress
(
"0x123"
),
common
.
HexToAddress
(
"0x456"
),
},
addrs
)
},
},
{
name
:
"extra input addresses"
,
totalSupply
:
big
.
NewInt
(
1
),
expDiff
:
big
.
NewInt
(
0
),
stateBalances
:
map
[
common
.
Address
]
*
big
.
Int
{
common
.
HexToAddress
(
"0x123"
)
:
big
.
NewInt
(
1
),
},
inputAddresses
:
[]
common
.
Address
{
common
.
HexToAddress
(
"0x123"
),
common
.
HexToAddress
(
"0x456"
),
},
check
:
func
(
t
*
testing
.
T
,
addrs
FilteredOVMETHAddresses
,
err
error
)
{
require
.
NoError
(
t
,
err
)
require
.
EqualValues
(
t
,
FilteredOVMETHAddresses
{
common
.
HexToAddress
(
"0x123"
),
},
addrs
)
},
},
{
name
:
"extra input allowances"
,
totalSupply
:
big
.
NewInt
(
1
),
expDiff
:
big
.
NewInt
(
0
),
stateBalances
:
map
[
common
.
Address
]
*
big
.
Int
{
common
.
HexToAddress
(
"0x123"
)
:
big
.
NewInt
(
1
),
},
stateAllowances
:
map
[
common
.
Address
]
common
.
Address
{
common
.
HexToAddress
(
"0x123"
)
:
common
.
HexToAddress
(
"0x456"
),
},
inputAddresses
:
[]
common
.
Address
{
common
.
HexToAddress
(
"0x123"
),
common
.
HexToAddress
(
"0x456"
),
},
inputAllowances
:
[]
*
crossdomain
.
Allowance
{
{
From
:
common
.
HexToAddress
(
"0x123"
),
To
:
common
.
HexToAddress
(
"0x456"
),
},
{
From
:
common
.
HexToAddress
(
"0x123"
),
To
:
common
.
HexToAddress
(
"0x789"
),
},
},
check
:
func
(
t
*
testing
.
T
,
addrs
FilteredOVMETHAddresses
,
err
error
)
{
require
.
NoError
(
t
,
err
)
require
.
EqualValues
(
t
,
FilteredOVMETHAddresses
{
common
.
HexToAddress
(
"0x123"
),
},
addrs
)
},
},
{
name
:
"missing input addresses"
,
totalSupply
:
big
.
NewInt
(
2
),
expDiff
:
big
.
NewInt
(
0
),
stateBalances
:
map
[
common
.
Address
]
*
big
.
Int
{
common
.
HexToAddress
(
"0x123"
)
:
big
.
NewInt
(
1
),
common
.
HexToAddress
(
"0x456"
)
:
big
.
NewInt
(
1
),
},
inputAddresses
:
[]
common
.
Address
{
common
.
HexToAddress
(
"0x123"
),
},
check
:
func
(
t
*
testing
.
T
,
addrs
FilteredOVMETHAddresses
,
err
error
)
{
require
.
Error
(
t
,
err
)
require
.
ErrorContains
(
t
,
err
,
"unknown storage slot"
)
},
},
{
name
:
"missing input allowances"
,
totalSupply
:
big
.
NewInt
(
2
),
expDiff
:
big
.
NewInt
(
0
),
stateBalances
:
map
[
common
.
Address
]
*
big
.
Int
{
common
.
HexToAddress
(
"0x123"
)
:
big
.
NewInt
(
1
),
},
stateAllowances
:
map
[
common
.
Address
]
common
.
Address
{
common
.
HexToAddress
(
"0x123"
)
:
common
.
HexToAddress
(
"0x456"
),
common
.
HexToAddress
(
"0x123"
)
:
common
.
HexToAddress
(
"0x789"
),
},
inputAddresses
:
[]
common
.
Address
{
common
.
HexToAddress
(
"0x123"
),
},
inputAllowances
:
[]
*
crossdomain
.
Allowance
{
{
From
:
common
.
HexToAddress
(
"0x123"
),
To
:
common
.
HexToAddress
(
"0x456"
),
},
},
check
:
func
(
t
*
testing
.
T
,
addrs
FilteredOVMETHAddresses
,
err
error
)
{
require
.
Error
(
t
,
err
)
require
.
ErrorContains
(
t
,
err
,
"unknown storage slot"
)
},
},
{
name
:
"bad supply diff"
,
totalSupply
:
big
.
NewInt
(
4
),
expDiff
:
big
.
NewInt
(
0
),
stateBalances
:
map
[
common
.
Address
]
*
big
.
Int
{
common
.
HexToAddress
(
"0x123"
)
:
big
.
NewInt
(
1
),
common
.
HexToAddress
(
"0x456"
)
:
big
.
NewInt
(
2
),
},
inputAddresses
:
[]
common
.
Address
{
common
.
HexToAddress
(
"0x123"
),
common
.
HexToAddress
(
"0x456"
),
},
check
:
func
(
t
*
testing
.
T
,
addrs
FilteredOVMETHAddresses
,
err
error
)
{
require
.
Error
(
t
,
err
)
require
.
ErrorContains
(
t
,
err
,
"supply mismatch"
)
},
},
{
name
:
"good supply diff"
,
totalSupply
:
big
.
NewInt
(
4
),
expDiff
:
big
.
NewInt
(
1
),
stateBalances
:
map
[
common
.
Address
]
*
big
.
Int
{
common
.
HexToAddress
(
"0x123"
)
:
big
.
NewInt
(
1
),
common
.
HexToAddress
(
"0x456"
)
:
big
.
NewInt
(
2
),
},
inputAddresses
:
[]
common
.
Address
{
common
.
HexToAddress
(
"0x123"
),
common
.
HexToAddress
(
"0x456"
),
},
check
:
func
(
t
*
testing
.
T
,
addrs
FilteredOVMETHAddresses
,
err
error
)
{
require
.
NoError
(
t
,
err
)
require
.
EqualValues
(
t
,
FilteredOVMETHAddresses
{
common
.
HexToAddress
(
"0x123"
),
common
.
HexToAddress
(
"0x456"
),
},
addrs
)
},
},
}
for
_
,
tt
:=
range
tests
{
t
.
Run
(
tt
.
name
,
func
(
t
*
testing
.
T
)
{
db
:=
makeLegacyETH
(
t
,
tt
.
totalSupply
,
tt
.
stateBalances
,
tt
.
stateAllowances
)
factory
:=
func
()
(
*
state
.
StateDB
,
error
)
{
return
db
,
nil
}
addrs
,
err
:=
doMigration
(
factory
,
tt
.
inputAddresses
,
tt
.
inputAllowances
,
tt
.
expDiff
,
false
)
// Sort the addresses since they come in in a random order.
sort
.
Slice
(
addrs
,
func
(
i
,
j
int
)
bool
{
return
bytes
.
Compare
(
addrs
[
i
][
:
],
addrs
[
j
][
:
])
<
0
})
tt
.
check
(
t
,
addrs
,
err
)
})
}
}
func
makeLegacyETH
(
t
*
testing
.
T
,
totalSupply
*
big
.
Int
,
balances
map
[
common
.
Address
]
*
big
.
Int
,
allowances
map
[
common
.
Address
]
common
.
Address
)
*
state
.
StateDB
{
db
,
err
:=
state
.
New
(
common
.
Hash
{},
state
.
NewDatabaseWithConfig
(
rawdb
.
NewMemoryDatabase
(),
&
trie
.
Config
{
Preimages
:
true
,
Cache
:
1024
,
}),
nil
)
require
.
NoError
(
t
,
err
)
db
.
CreateAccount
(
OVMETHAddress
)
db
.
SetState
(
OVMETHAddress
,
getOVMETHTotalSupplySlot
(),
common
.
BigToHash
(
totalSupply
))
for
slot
:=
range
ignoredSlots
{
if
slot
==
getOVMETHTotalSupplySlot
()
{
continue
}
db
.
SetState
(
OVMETHAddress
,
slot
,
common
.
Hash
{
31
:
0xff
})
}
for
addr
,
balance
:=
range
balances
{
db
.
SetState
(
OVMETHAddress
,
CalcOVMETHStorageKey
(
addr
),
common
.
BigToHash
(
balance
))
}
for
from
,
to
:=
range
allowances
{
db
.
SetState
(
OVMETHAddress
,
CalcAllowanceStorageKey
(
from
,
to
),
common
.
BigToHash
(
big
.
NewInt
(
1
)))
}
root
,
err
:=
db
.
Commit
(
false
)
require
.
NoError
(
t
,
err
)
err
=
db
.
Database
()
.
TrieDB
()
.
Commit
(
root
,
true
)
require
.
NoError
(
t
,
err
)
return
db
}
// TestPreCheckBalancesRandom tests that the pre-check balances function works
// with random addresses. This test makes sure that the partition logic doesn't
// miss anything.
func
TestPreCheckBalancesRandom
(
t
*
testing
.
T
)
{
addresses
:=
make
([]
common
.
Address
,
0
)
stateBalances
:=
make
(
map
[
common
.
Address
]
*
big
.
Int
)
allowances
:=
make
([]
*
crossdomain
.
Allowance
,
0
)
stateAllowances
:=
make
(
map
[
common
.
Address
]
common
.
Address
)
totalSupply
:=
big
.
NewInt
(
0
)
for
i
:=
0
;
i
<
100
;
i
++
{
for
i
:=
0
;
i
<
rand
.
Intn
(
1000
);
i
++
{
addr
:=
randAddr
(
t
)
addresses
=
append
(
addresses
,
addr
)
stateBalances
[
addr
]
=
big
.
NewInt
(
int64
(
rand
.
Intn
(
1
_000_000
)))
totalSupply
=
new
(
big
.
Int
)
.
Add
(
totalSupply
,
stateBalances
[
addr
])
}
sort
.
Slice
(
addresses
,
func
(
i
,
j
int
)
bool
{
return
bytes
.
Compare
(
addresses
[
i
][
:
],
addresses
[
j
][
:
])
<
0
})
for
i
:=
0
;
i
<
rand
.
Intn
(
1000
);
i
++
{
addr
:=
randAddr
(
t
)
to
:=
randAddr
(
t
)
allowances
=
append
(
allowances
,
&
crossdomain
.
Allowance
{
From
:
addr
,
To
:
to
,
})
stateAllowances
[
addr
]
=
to
}
db
:=
makeLegacyETH
(
t
,
totalSupply
,
stateBalances
,
stateAllowances
)
factory
:=
func
()
(
*
state
.
StateDB
,
error
)
{
return
db
,
nil
}
outAddrs
,
err
:=
doMigration
(
factory
,
addresses
,
allowances
,
big
.
NewInt
(
0
),
false
)
require
.
NoError
(
t
,
err
)
sort
.
Slice
(
outAddrs
,
func
(
i
,
j
int
)
bool
{
return
bytes
.
Compare
(
outAddrs
[
i
][
:
],
outAddrs
[
j
][
:
])
<
0
})
require
.
EqualValues
(
t
,
addresses
,
outAddrs
)
}
}
func
randAddr
(
t
*
testing
.
T
)
common
.
Address
{
var
addr
common
.
Address
_
,
err
:=
rand
.
Read
(
addr
[
:
])
require
.
NoError
(
t
,
err
)
return
addr
}
op-chain-ops/genesis/check.go
View file @
60129ad5
...
@@ -7,6 +7,8 @@ import (
...
@@ -7,6 +7,8 @@ import (
"fmt"
"fmt"
"math/big"
"math/big"
"github.com/ethereum-optimism/optimism/op-chain-ops/ether"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state"
...
@@ -251,7 +253,7 @@ func PostCheckPredeploys(prevDB, currDB *state.StateDB) error {
...
@@ -251,7 +253,7 @@ func PostCheckPredeploys(prevDB, currDB *state.StateDB) error {
// Balances and nonces should match legacy
// Balances and nonces should match legacy
oldNonce
:=
prevDB
.
GetNonce
(
addr
)
oldNonce
:=
prevDB
.
GetNonce
(
addr
)
oldBalance
:=
prevDB
.
GetBalance
(
addr
)
oldBalance
:=
ether
.
GetOVMETHBalance
(
prevDB
,
addr
)
newNonce
:=
currDB
.
GetNonce
(
addr
)
newNonce
:=
currDB
.
GetNonce
(
addr
)
newBalance
:=
currDB
.
GetBalance
(
addr
)
newBalance
:=
currDB
.
GetBalance
(
addr
)
if
oldNonce
!=
newNonce
{
if
oldNonce
!=
newNonce
{
...
@@ -543,7 +545,7 @@ func CheckWithdrawalsAfter(db vm.StateDB, data crossdomain.MigrationData, l1Cros
...
@@ -543,7 +545,7 @@ func CheckWithdrawalsAfter(db vm.StateDB, data crossdomain.MigrationData, l1Cros
// If the sender is _not_ the L2XDM, the value should not be migrated.
// If the sender is _not_ the L2XDM, the value should not be migrated.
wd
:=
wdsByOldSlot
[
key
]
wd
:=
wdsByOldSlot
[
key
]
if
wd
.
XDomain
Sender
==
predeploys
.
L2CrossDomainMessengerAddr
{
if
wd
.
Message
Sender
==
predeploys
.
L2CrossDomainMessengerAddr
{
// Make sure the value is abiTrue if this withdrawal should be migrated.
// Make sure the value is abiTrue if this withdrawal should be migrated.
if
migratedValue
!=
abiTrue
{
if
migratedValue
!=
abiTrue
{
innerErr
=
fmt
.
Errorf
(
"expected migrated value to be true, but got %s"
,
migratedValue
)
innerErr
=
fmt
.
Errorf
(
"expected migrated value to be true, but got %s"
,
migratedValue
)
...
@@ -552,7 +554,7 @@ func CheckWithdrawalsAfter(db vm.StateDB, data crossdomain.MigrationData, l1Cros
...
@@ -552,7 +554,7 @@ func CheckWithdrawalsAfter(db vm.StateDB, data crossdomain.MigrationData, l1Cros
}
else
{
}
else
{
// Otherwise, ensure that withdrawals from senders other than the L2XDM are _not_ migrated.
// Otherwise, ensure that withdrawals from senders other than the L2XDM are _not_ migrated.
if
migratedValue
!=
abiFalse
{
if
migratedValue
!=
abiFalse
{
innerErr
=
fmt
.
Errorf
(
"a migration from a sender other than the L2XDM was migrated
"
)
innerErr
=
fmt
.
Errorf
(
"a migration from a sender other than the L2XDM was migrated
. sender: %s, migrated value: %s"
,
wd
.
MessageSender
,
migratedValue
)
return
false
return
false
}
}
}
}
...
...
op-chain-ops/genesis/db_migration.go
View file @
60129ad5
...
@@ -82,6 +82,7 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m
...
@@ -82,6 +82,7 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m
)
)
}
}
dbFactory
:=
func
()
(
*
state
.
StateDB
,
error
)
{
// Set up the backing store.
// Set up the backing store.
underlyingDB
:=
state
.
NewDatabaseWithConfig
(
ldb
,
&
trie
.
Config
{
underlyingDB
:=
state
.
NewDatabaseWithConfig
(
ldb
,
&
trie
.
Config
{
Preimages
:
true
,
Preimages
:
true
,
...
@@ -94,6 +95,14 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m
...
@@ -94,6 +95,14 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m
return
nil
,
fmt
.
Errorf
(
"cannot open StateDB: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"cannot open StateDB: %w"
,
err
)
}
}
return
db
,
nil
}
db
,
err
:=
dbFactory
()
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot create StateDB: %w"
,
err
)
}
// Before we do anything else, we need to ensure that all of the input configuration is correct
// Before we do anything else, we need to ensure that all of the input configuration is correct
// and nothing is missing. We'll first verify the contract configuration, then we'll verify the
// and nothing is missing. We'll first verify the contract configuration, then we'll verify the
// witness data for the migration. We operate under the assumption that the witness data is
// witness data for the migration. We operate under the assumption that the witness data is
...
@@ -139,7 +148,7 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m
...
@@ -139,7 +148,7 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m
// Unlike with withdrawals, we do not need to filter out extra addresses because their balances
// Unlike with withdrawals, we do not need to filter out extra addresses because their balances
// would necessarily be zero and therefore not affect the migration.
// would necessarily be zero and therefore not affect the migration.
log
.
Info
(
"Checking addresses..."
,
"no-check"
,
noCheck
)
log
.
Info
(
"Checking addresses..."
,
"no-check"
,
noCheck
)
addrs
,
err
:=
ether
.
PreCheckBalances
(
ldb
,
db
,
migrationData
.
Addresses
(),
migrationData
.
OvmAllowances
,
int
(
config
.
L1ChainID
),
noCheck
)
addrs
,
err
:=
ether
.
PreCheckBalances
(
dbFactory
,
migrationData
.
Addresses
(),
migrationData
.
OvmAllowances
,
int
(
config
.
L1ChainID
),
noCheck
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"addresses mismatch: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"addresses mismatch: %w"
,
err
)
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment