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
31532ce1
Unverified
Commit
31532ce1
authored
Jan 09, 2023
by
Matthew Slipper
Committed by
GitHub
Jan 09, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4605 from ethereum-optimism/sc/ops-migration-cleanup-1
feat(ops): clean up migration process
parents
0c384d66
365bf05b
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
728 additions
and
306 deletions
+728
-306
main.go
op-chain-ops/cmd/op-migrate/main.go
+20
-1
precheck.go
op-chain-ops/crossdomain/precheck.go
+77
-0
migrate.go
op-chain-ops/ether/migrate.go
+39
-182
precheck.go
op-chain-ops/ether/precheck.go
+160
-0
check.go
op-chain-ops/genesis/check.go
+232
-11
db_migration.go
op-chain-ops/genesis/db_migration.go
+107
-95
setters.go
op-chain-ops/genesis/setters.go
+55
-17
go.mod
op-chain-ops/go.mod
+2
-0
go.sum
op-chain-ops/go.sum
+36
-0
No files found.
op-chain-ops/cmd/op-migrate/main.go
View file @
31532ce1
...
...
@@ -9,6 +9,10 @@ import (
"path/filepath"
"strings"
"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/core/rawdb"
...
...
@@ -195,7 +199,22 @@ func main() {
return
err
}
if
err
:=
genesis
.
PostCheckMigratedDB
(
postLDB
,
migrationData
,
&
config
.
L1CrossDomainMessengerProxy
,
config
.
L1ChainID
);
err
!=
nil
{
if
err
:=
genesis
.
PostCheckMigratedDB
(
postLDB
,
migrationData
,
&
config
.
L1CrossDomainMessengerProxy
,
config
.
L1ChainID
,
config
.
FinalSystemOwner
,
&
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
}
...
...
op-chain-ops/crossdomain/precheck.go
0 → 100644
View file @
31532ce1
package
crossdomain
import
(
"fmt"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/log"
)
// PreCheckWithdrawals checks that the given list of withdrawals represents all withdrawals made
// in the legacy system and filters out any extra withdrawals not included in the legacy system.
func
PreCheckWithdrawals
(
db
*
state
.
StateDB
,
withdrawals
[]
*
LegacyWithdrawal
)
([]
*
LegacyWithdrawal
,
error
)
{
// Convert each withdrawal into a storage slot, and build a map of those slots.
slotsInp
:=
make
(
map
[
common
.
Hash
]
*
LegacyWithdrawal
)
for
_
,
wd
:=
range
withdrawals
{
slot
,
err
:=
wd
.
StorageSlot
()
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot check withdrawals: %w"
,
err
)
}
slotsInp
[
slot
]
=
wd
}
// Build a mapping of the slots of all messages actually sent in the legacy system.
var
count
int
slotsAct
:=
make
(
map
[
common
.
Hash
]
bool
)
err
:=
db
.
ForEachStorage
(
predeploys
.
LegacyMessagePasserAddr
,
func
(
key
,
value
common
.
Hash
)
bool
{
// When a message is inserted into the LegacyMessagePasser, it is stored with the value
// of the ABI encoding of "true". Although there should not be any other storage slots, we
// can safely ignore anything that is not "true".
if
value
!=
abiTrue
{
// Should not happen!
log
.
Error
(
"found unknown slot in LegacyMessagePasser"
,
"key"
,
key
.
String
(),
"val"
,
value
.
String
())
return
true
}
// Slot exists, so add it to the map.
slotsAct
[
key
]
=
true
count
++
return
true
})
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot iterate over LegacyMessagePasser: %w"
,
err
)
}
// Log the number of messages we found.
log
.
Info
(
"Iterated legacy messages"
,
"count"
,
count
)
// Iterate over the list of actual slots and check that we have an input message for each one.
for
slot
:=
range
slotsAct
{
_
,
ok
:=
slotsInp
[
slot
]
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"unknown storage slot in state: %s"
,
slot
)
}
}
// Iterate over the list of input messages and check that we have a known slot for each one.
// We'll filter out any extra messages that are not in the legacy system.
filtered
:=
make
([]
*
LegacyWithdrawal
,
0
)
for
slot
:=
range
slotsInp
{
_
,
ok
:=
slotsAct
[
slot
]
if
!
ok
{
log
.
Info
(
"filtering out unknown input message"
,
"slot"
,
slot
.
String
())
continue
}
filtered
=
append
(
filtered
,
slotsInp
[
slot
])
}
// At this point, we know that the list of filtered withdrawals MUST be exactly the same as the
// list of withdrawals in the state. If we didn't have enough withdrawals, we would've errored
// out, and if we had too many, we would've filtered them out.
return
filtered
,
nil
}
op-chain-ops/ether/migrate.go
View file @
31532ce1
...
...
@@ -8,13 +8,9 @@ import (
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis/migration"
"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/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)
var
(
...
...
@@ -33,166 +29,29 @@ var (
}
)
func
MigrateLegacyETH
(
db
ethdb
.
Database
,
stateDB
*
state
.
StateDB
,
addresses
[]
common
.
Address
,
allowances
[]
*
migration
.
Allowance
,
chainID
int
,
noCheck
bool
)
error
{
// Set of addresses that we will be migrating.
addressesToMigrate
:=
make
(
map
[
common
.
Address
]
bool
)
// Set of storage slots that we expect to see in the OVM ETH contract.
storageSlotsToMigrate
:=
make
(
map
[
common
.
Hash
]
int
)
func
MigrateLegacyETH
(
ldb
ethdb
.
Database
,
db
*
state
.
StateDB
,
addresses
[]
common
.
Address
,
chainID
int
,
noCheck
bool
)
error
{
// Chain params to use for integrity checking.
params
:=
migration
.
ParamsByChainID
[
chainID
]
if
params
==
nil
{
return
fmt
.
Errorf
(
"no chain params for %d"
,
chainID
)
}
// Log the chain params for debugging purposes.
log
.
Info
(
"Chain params"
,
"chain-id"
,
chainID
,
"supply-delta"
,
params
.
ExpectedSupplyDelta
)
// Iterate over each address list, and read the addresses they
// contain into memory. Also calculate the storage slots for each
// address.
// Deduplicate the list of addresses by converting to a map.
deduped
:=
make
(
map
[
common
.
Address
]
bool
)
for
_
,
addr
:=
range
addresses
{
addressesToMigrate
[
addr
]
=
true
storageSlotsToMigrate
[
CalcOVMETHStorageKey
(
addr
)]
=
1
}
for
_
,
allowance
:=
range
allowances
{
addressesToMigrate
[
allowance
.
From
]
=
true
storageSlotsToMigrate
[
CalcAllowanceStorageKey
(
allowance
.
From
,
allowance
.
To
)]
=
2
}
if
chainID
==
1
{
// Some folks sent money to this address ages ago, permanently locking it
// there. This contract never transacted on a modern network, so hardcode
// this to ensure that all storage slots are accounted for.
// This address was once the OVM_SequencerEntrypoint contract.
seqEntryAddr
:=
common
.
HexToAddress
(
"0x4200000000000000000000000000000000000005"
)
addressesToMigrate
[
seqEntryAddr
]
=
true
storageSlotsToMigrate
[
CalcOVMETHStorageKey
(
seqEntryAddr
)]
=
1
}
headBlock
:=
rawdb
.
ReadHeadBlock
(
db
)
root
:=
headBlock
.
Root
()
// Read mint events from the database. Even though Geth's balance methods
// are instrumented, mints from the bridge happen in the EVM and so do
// not execute that code path. As a result, we parse mint events in order
// to not miss any balances.
log
.
Info
(
"reading mint events from DB"
)
logProgress
:=
ProgressLogger
(
100
,
"read mint events"
)
err
:=
IterateMintEvents
(
db
,
headBlock
.
NumberU64
(),
func
(
address
common
.
Address
,
headNum
uint64
)
error
{
addressesToMigrate
[
address
]
=
true
storageSlotsToMigrate
[
CalcOVMETHStorageKey
(
address
)]
=
1
logProgress
(
"headnum"
,
headNum
)
return
nil
})
if
err
!=
nil
{
return
wrapErr
(
err
,
"error reading mint events"
)
}
// Make sure all addresses are accounted for by iterating over
// the OVM ETH contract's state, and panicking if we miss
// any storage keys. We also keep track of the total amount of
// OVM ETH found, and diff that against the total supply of
// OVM ETH specified in the contract.
backingStateDB
:=
state
.
NewDatabaseWithConfig
(
db
,
&
trie
.
Config
{
Preimages
:
true
,
})
if
err
!=
nil
{
return
wrapErr
(
err
,
"error opening state DB"
)
}
storageTrie
:=
stateDB
.
StorageTrie
(
OVMETHAddress
)
storageIt
:=
trie
.
NewIterator
(
storageTrie
.
NodeIterator
(
nil
))
logProgress
=
ProgressLogger
(
10000
,
"iterating storage keys"
)
totalFound
:=
new
(
big
.
Int
)
totalSupply
:=
getOVMETHTotalSupply
(
stateDB
)
for
storageIt
.
Next
()
{
_
,
content
,
_
,
err
:=
rlp
.
Split
(
storageIt
.
Value
)
if
err
!=
nil
{
panic
(
err
)
}
k
:=
common
.
BytesToHash
(
storageTrie
.
GetKey
(
storageIt
.
Key
))
v
:=
common
.
BytesToHash
(
content
)
sType
:=
storageSlotsToMigrate
[
k
]
switch
sType
{
case
1
:
// This slot is a balance, increment totalFound.
totalFound
=
totalFound
.
Add
(
totalFound
,
v
.
Big
())
case
2
:
// This slot is an allowance, ignore it.
continue
default
:
// Check if this slot is a variable. If it isn't, abort.
if
!
ignoredSlots
[
k
]
{
if
noCheck
{
log
.
Error
(
"missed storage key"
,
"k"
,
k
.
String
(),
"v"
,
v
.
String
())
}
else
{
log
.
Crit
(
"missed storage key"
,
"k"
,
k
.
String
(),
"v"
,
v
.
String
())
}
}
}
logProgress
()
}
// Verify that the total supply is what we expect. We allow a hardcoded
// delta to be specified in the chain params since older regenesis events
// had supply bugs.
delta
:=
new
(
big
.
Int
)
.
Sub
(
totalSupply
,
totalFound
)
if
delta
.
Cmp
(
params
.
ExpectedSupplyDelta
)
!=
0
{
if
noCheck
{
log
.
Error
(
"supply mismatch"
,
"migrated"
,
totalFound
.
String
(),
"supply"
,
totalSupply
.
String
(),
"delta"
,
delta
.
String
(),
"exp_delta"
,
params
.
ExpectedSupplyDelta
.
String
(),
)
}
else
{
log
.
Crit
(
"supply mismatch"
,
"migrated"
,
totalFound
.
String
(),
"supply"
,
totalSupply
.
String
(),
"delta"
,
delta
.
String
(),
"exp_delta"
,
params
.
ExpectedSupplyDelta
.
String
(),
)
deduped
[
addr
]
=
true
}
}
log
.
Info
(
"supply verified OK"
,
"migrated"
,
totalFound
.
String
(),
"supply"
,
totalSupply
.
String
(),
"delta"
,
delta
.
String
(),
"exp_delta"
,
params
.
ExpectedSupplyDelta
.
String
(),
)
log
.
Info
(
"performing migration"
)
log
.
Info
(
"trie dumping started"
,
"root"
,
root
)
tr
,
err
:=
backingStateDB
.
OpenTrie
(
root
)
if
err
!=
nil
{
return
err
}
it
:=
trie
.
NewIterator
(
tr
.
NodeIterator
(
nil
))
// Migrate the legacy ETH to ETH.
log
.
Info
(
"Migrating legacy ETH to ETH"
,
"num-accounts"
,
len
(
addresses
))
totalMigrated
:=
new
(
big
.
Int
)
logAccountProgress
:=
ProgressLogger
(
1000
,
"imported accounts"
)
migratedAccounts
:=
make
(
map
[
common
.
Address
]
bool
)
for
it
.
Next
()
{
// It's up to us to decode trie data.
var
data
types
.
StateAccount
if
err
:=
rlp
.
DecodeBytes
(
it
.
Value
,
&
data
);
err
!=
nil
{
panic
(
err
)
}
addrBytes
:=
tr
.
GetKey
(
it
.
Key
)
addr
:=
common
.
BytesToAddress
(
addrBytes
)
migratedAccounts
[
addr
]
=
true
// Get the OVM ETH balance based on the address's storage key.
ovmBalance
:=
getOVMETHBalance
(
stateDB
,
addr
)
for
addr
:=
range
deduped
{
// No accounts should have a balance in state. If they do, bail.
if
d
ata
.
Balance
.
Sign
()
>
0
{
if
d
b
.
GetBalance
(
addr
)
.
Sign
()
>
0
{
if
noCheck
{
log
.
Error
(
"account has non-zero balance in state - should never happen"
,
"addr"
,
addr
)
}
else
{
...
...
@@ -200,54 +59,52 @@ func MigrateLegacyETH(db ethdb.Database, stateDB *state.StateDB, addresses []com
}
}
// Pull out the OVM ETH balance.
ovmBalance
:=
getOVMETHBalance
(
db
,
addr
)
// Actually perform the migration by setting the appropriate values in state.
stateDB
.
SetBalance
(
addr
,
ovmBalance
)
stateDB
.
SetState
(
predeploys
.
LegacyERC20ETHAddr
,
CalcOVMETHStorageKey
(
addr
),
common
.
Hash
{})
db
.
SetBalance
(
addr
,
ovmBalance
)
db
.
SetState
(
predeploys
.
LegacyERC20ETHAddr
,
CalcOVMETHStorageKey
(
addr
),
common
.
Hash
{})
// Bump the total OVM balance.
totalMigrated
=
totalMigrated
.
Add
(
totalMigrated
,
ovmBalance
)
// Log progress.
logAccountProgress
()
}
// Take care of nonce zero accounts with balances. These are accounts
// that received OVM ETH as part of the regenesis, but never actually
// transacted on-chain.
logNonceZeroProgress
:=
ProgressLogger
(
1000
,
"imported zero nonce accounts"
)
log
.
Info
(
"importing accounts with zero-nonce balances"
)
for
addr
:=
range
addressesToMigrate
{
if
migratedAccounts
[
addr
]
{
continue
}
ovmBalance
:=
getOVMETHBalance
(
stateDB
,
addr
)
totalMigrated
=
totalMigrated
.
Add
(
totalMigrated
,
ovmBalance
)
stateDB
.
AddBalance
(
addr
,
ovmBalance
)
stateDB
.
SetState
(
predeploys
.
LegacyERC20ETHAddr
,
CalcOVMETHStorageKey
(
addr
),
common
.
Hash
{})
logNonceZeroProgress
()
}
// Make sure that the amount we migrated matches the amount in
// our original state.
if
totalMigrated
.
Cmp
(
totalFound
)
!=
0
{
// Make sure that the total supply delta matches the expected delta. This is equivalent to
// checking that the total migrated is equal to the total found, since we already performed the
// same check against the total found (a = b, b = c => a = c).
totalSupply
:=
getOVMETHTotalSupply
(
db
)
delta
:=
new
(
big
.
Int
)
.
Sub
(
totalSupply
,
totalMigrated
)
if
delta
.
Cmp
(
params
.
ExpectedSupplyDelta
)
!=
0
{
if
noCheck
{
log
.
Debug
(
"total migrated does not equal total OVM eth found"
,
"migrated"
,
totalMigrated
,
"found"
,
totalFound
,
log
.
Error
(
"supply mismatch"
,
"migrated"
,
totalMigrated
.
String
(),
"supply"
,
totalSupply
.
String
(),
"delta"
,
delta
.
String
(),
"exp_delta"
,
params
.
ExpectedSupplyDelta
.
String
(),
)
}
else
{
log
.
Crit
(
"total migrated does not equal total OVM eth found"
,
"migrated"
,
totalMigrated
,
"found"
,
totalFound
,
"supply mismatch"
,
"migrated"
,
totalMigrated
.
String
(),
"supply"
,
totalSupply
.
String
(),
"delta"
,
delta
.
String
(),
"exp_delta"
,
params
.
ExpectedSupplyDelta
.
String
(),
)
}
}
// Set the total supply to 0
stateDB
.
SetState
(
predeploys
.
LegacyERC20ETHAddr
,
getOVMETHTotalSupplySlot
(),
common
.
Hash
{})
// Set the total supply to 0. We do this because the total supply is necessarily going to be
// different than the sum of all balances since we no longer track balances inside the contract
// itself. The total supply is going to be weird no matter what, might as well set it to zero
// so it's explicitly weird instead of implicitly weird.
db
.
SetState
(
predeploys
.
LegacyERC20ETHAddr
,
getOVMETHTotalSupplySlot
(),
common
.
Hash
{})
log
.
Info
(
"Set the totalSupply to 0"
)
// Fin.
return
nil
}
op-chain-ops/ether/precheck.go
0 → 100644
View file @
31532ce1
package
ether
import
(
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis/migration"
"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/ethdb"
"github.com/ethereum/go-ethereum/log"
)
// 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
// 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.
func
PreCheckBalances
(
ldb
ethdb
.
Database
,
db
*
state
.
StateDB
,
addresses
[]
common
.
Address
,
allowances
[]
*
migration
.
Allowance
,
chainID
int
,
noCheck
bool
)
([]
common
.
Address
,
error
)
{
// Chain params to use for integrity checking.
params
:=
migration
.
ParamsByChainID
[
chainID
]
if
params
==
nil
{
return
nil
,
fmt
.
Errorf
(
"no chain params for %d"
,
chainID
)
}
// 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.
addrs
:=
make
([]
common
.
Address
,
0
)
slotsInp
:=
make
(
map
[
common
.
Hash
]
int
)
// For each known address, compute its balance key and add it to the list of addresses.
for
_
,
addr
:=
range
addresses
{
addrs
=
append
(
addrs
,
addr
)
slotsInp
[
CalcOVMETHStorageKey
(
addr
)]
=
1
}
// For each known allowance, compute its storage key and add it to the list of addresses.
for
_
,
allowance
:=
range
allowances
{
addrs
=
append
(
addrs
,
allowance
.
From
)
slotsInp
[
CalcAllowanceStorageKey
(
allowance
.
From
,
allowance
.
To
)]
=
2
}
// 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.
sequencerEntrypointAddr
:=
common
.
HexToAddress
(
"0x4200000000000000000000000000000000000005"
)
addrs
=
append
(
addrs
,
sequencerEntrypointAddr
)
slotsInp
[
CalcOVMETHStorageKey
(
sequencerEntrypointAddr
)]
=
1
// Also extract addresses/slots from Mint events. Our instrumentation currently only looks at
// direct balance changes inside of Geth, but Mint events mutate the ERC20 storage directly and
// therefore aren't picked up by our instrumentation. Instead of updating the instrumentation,
// we can simply iterate over every Mint event and add the address to the list of addresses.
log
.
Info
(
"Reading mint events from DB"
)
headBlock
:=
rawdb
.
ReadHeadBlock
(
ldb
)
logProgress
:=
ProgressLogger
(
100
,
"read mint events"
)
err
:=
IterateMintEvents
(
ldb
,
headBlock
.
NumberU64
(),
func
(
address
common
.
Address
,
headNum
uint64
)
error
{
addrs
=
append
(
addrs
,
address
)
slotsInp
[
CalcOVMETHStorageKey
(
address
)]
=
1
logProgress
(
"headnum"
,
headNum
)
return
nil
})
if
err
!=
nil
{
return
nil
,
wrapErr
(
err
,
"error reading mint events"
)
}
// Build a mapping of every storage slot in the LegacyERC20ETH contract, except the list of
// slots that we know we can ignore (totalSupply, name, symbol).
var
count
int
slotsAct
:=
make
(
map
[
common
.
Hash
]
common
.
Hash
)
err
=
db
.
ForEachStorage
(
predeploys
.
LegacyERC20ETHAddr
,
func
(
key
,
value
common
.
Hash
)
bool
{
// We can safely ignore specific slots (totalSupply, name, symbol).
if
ignoredSlots
[
key
]
{
return
true
}
// Slot exists, so add it to the map.
slotsAct
[
key
]
=
value
count
++
return
true
})
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot iterate over LegacyERC20ETHAddr: %w"
,
err
)
}
// Log how many slots were iterated over.
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
// keep track of the total balance to be migrated and throw if the total supply exceeds the
// expected supply delta.
totalFound
:=
new
(
big
.
Int
)
for
slot
:=
range
slotsAct
{
slotType
,
ok
:=
slotsInp
[
slot
]
if
!
ok
{
if
noCheck
{
log
.
Error
(
"ignoring unknown storage slot in state"
,
"slot"
,
slot
)
}
else
{
log
.
Crit
(
"unknown storage slot in state: %s"
,
slot
)
}
}
// Add balances to the total found.
switch
slotType
{
case
1
:
// Balance slot.
totalFound
.
Add
(
totalFound
,
slotsAct
[
slot
]
.
Big
())
case
2
:
// Allowance slot.
continue
default
:
// Should never happen.
if
noCheck
{
log
.
Error
(
"unknown slot type"
,
"slot"
,
slot
,
"type"
,
slotType
)
}
else
{
log
.
Crit
(
"unknown slot type: %d"
,
slotType
)
}
}
}
// 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
// cannot be reflected in the contract. This is fine because self-destructs just mean the L2 is
// actually *overcollateralized* by some tiny amount.
totalSupply
:=
getOVMETHTotalSupply
(
db
)
delta
:=
new
(
big
.
Int
)
.
Sub
(
totalSupply
,
totalFound
)
if
delta
.
Cmp
(
params
.
ExpectedSupplyDelta
)
!=
0
{
if
noCheck
{
log
.
Error
(
"supply mismatch"
,
"migrated"
,
totalFound
.
String
(),
"supply"
,
totalSupply
.
String
(),
"delta"
,
delta
.
String
(),
"exp_delta"
,
params
.
ExpectedSupplyDelta
.
String
(),
)
}
else
{
log
.
Crit
(
"supply mismatch"
,
"migrated"
,
totalFound
.
String
(),
"supply"
,
totalSupply
.
String
(),
"delta"
,
delta
.
String
(),
"exp_delta"
,
params
.
ExpectedSupplyDelta
.
String
(),
)
}
}
// Supply is verified.
log
.
Info
(
"supply verified OK"
,
"migrated"
,
totalFound
.
String
(),
"supply"
,
totalSupply
.
String
(),
"delta"
,
delta
.
String
(),
"exp_delta"
,
params
.
ExpectedSupplyDelta
.
String
(),
)
// We know we have at least a superset of all addresses here since we know that we have every
// storage slot. It's fine to have extras because they won't have any balance.
return
addrs
,
nil
}
op-chain-ops/genesis/check.go
View file @
31532ce1
...
...
@@ -2,10 +2,13 @@ package genesis
import
(
"bytes"
"encoding/binary"
"errors"
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis/migration"
"github.com/ethereum/go-ethereum/crypto"
...
...
@@ -26,7 +29,13 @@ import (
// in the future.
const
MaxSlotChecks
=
1000
var
LegacyETHCheckSlots
=
map
[
common
.
Hash
]
common
.
Hash
{
type
StorageCheckMap
=
map
[
common
.
Hash
]
common
.
Hash
var
(
L2XDMOwnerSlot
=
common
.
Hash
{
31
:
0x33
}
ProxyAdminOwnerSlot
=
common
.
Hash
{}
LegacyETHCheckSlots
=
map
[
common
.
Hash
]
common
.
Hash
{
// Bridge
common
.
Hash
{
31
:
0x06
}
:
common
.
HexToHash
(
"0x0000000000000000000000004200000000000000000000000000000000000010"
),
// Symbol
...
...
@@ -35,10 +44,53 @@ var LegacyETHCheckSlots = map[common.Hash]common.Hash{
common
.
Hash
{
31
:
0x03
}
:
common
.
HexToHash
(
"0x457468657200000000000000000000000000000000000000000000000000000a"
),
// Total supply
common
.
Hash
{
31
:
0x02
}
:
{},
}
}
// ExpectedStorageSlots is a map of predeploy addresses to the storage slots and values that are
// expected to be set in those predeploys after the migration. It does not include any predeploys
// that were not wiped. It also accounts for the 2 EIP-1967 storage slots in each contract.
// It does _not_ include L1Block. L1Block is checked separately.
ExpectedStorageSlots
=
map
[
common
.
Address
]
StorageCheckMap
{
predeploys
.
L2CrossDomainMessengerAddr
:
{
// Slot 0x00 (0) is a combination of spacer_0_0_20, _initialized, and _initializing
common
.
Hash
{}
:
common
.
HexToHash
(
"0x0000000000000000000000010000000000000000000000000000000000000000"
),
// Slot 0x33 (51) is _owner. Requires custom check, so set to a garbage value
L2XDMOwnerSlot
:
common
.
HexToHash
(
"0xbadbadbadbad0xbadbadbadbadbadbadbadbad0xbadbadbadbad0xbadbadbad0"
),
// Slot 0x97 (151) is _status
common
.
Hash
{
31
:
0x97
}
:
common
.
HexToHash
(
"0x0000000000000000000000000000000000000000000000000000000000000001"
),
// Slot 0xcc (204) is xDomainMsgSender
common
.
Hash
{
31
:
0xcc
}
:
common
.
HexToHash
(
"0x000000000000000000000000000000000000000000000000000000000000dead"
),
// EIP-1967 storage slots
AdminSlot
:
common
.
HexToHash
(
"0x0000000000000000000000004200000000000000000000000000000000000018"
),
ImplementationSlot
:
common
.
HexToHash
(
"0x000000000000000000000000c0d3c0d3c0d3c0d3c0d3c0d3c0d3c0d3c0d30007"
),
},
predeploys
.
L2StandardBridgeAddr
:
eip1967Slots
(
predeploys
.
L2StandardBridgeAddr
),
predeploys
.
SequencerFeeVaultAddr
:
eip1967Slots
(
predeploys
.
SequencerFeeVaultAddr
),
predeploys
.
OptimismMintableERC20FactoryAddr
:
eip1967Slots
(
predeploys
.
OptimismMintableERC20FactoryAddr
),
predeploys
.
L1BlockNumberAddr
:
eip1967Slots
(
predeploys
.
L1BlockNumberAddr
),
predeploys
.
GasPriceOracleAddr
:
eip1967Slots
(
predeploys
.
GasPriceOracleAddr
),
//predeploys.L1BlockAddr: eip1967Slots(predeploys.L1BlockAddr),
predeploys
.
L2ERC721BridgeAddr
:
eip1967Slots
(
predeploys
.
L2ERC721BridgeAddr
),
predeploys
.
OptimismMintableERC721FactoryAddr
:
eip1967Slots
(
predeploys
.
OptimismMintableERC721FactoryAddr
),
// ProxyAdmin is not a proxy, and only has the _owner slot set.
predeploys
.
ProxyAdminAddr
:
{
// Slot 0x00 (0) is _owner. Requires custom check, so set to a garbage value
ProxyAdminOwnerSlot
:
common
.
HexToHash
(
"0xbadbadbadbad0xbadbadbadbadbadbadbadbad0xbadbadbadbad0xbadbadbad0"
),
},
predeploys
.
BaseFeeVaultAddr
:
eip1967Slots
(
predeploys
.
BaseFeeVaultAddr
),
predeploys
.
L1FeeVaultAddr
:
eip1967Slots
(
predeploys
.
L1FeeVaultAddr
),
}
)
// PostCheckMigratedDB will check that the migration was performed correctly
func
PostCheckMigratedDB
(
ldb
ethdb
.
Database
,
migrationData
migration
.
MigrationData
,
l1XDM
*
common
.
Address
,
l1ChainID
uint64
)
error
{
func
PostCheckMigratedDB
(
ldb
ethdb
.
Database
,
migrationData
migration
.
MigrationData
,
l1XDM
*
common
.
Address
,
l1ChainID
uint64
,
finalSystemOwner
common
.
Address
,
info
*
derive
.
L1BlockInfo
,
)
error
{
log
.
Info
(
"Validating database migration"
)
hash
:=
rawdb
.
ReadHeadHeaderHash
(
ldb
)
...
...
@@ -67,6 +119,11 @@ func PostCheckMigratedDB(ldb ethdb.Database, migrationData migration.MigrationDa
return
fmt
.
Errorf
(
"cannot open StateDB: %w"
,
err
)
}
if
err
:=
PostCheckPredeployStorage
(
db
,
finalSystemOwner
);
err
!=
nil
{
return
err
}
log
.
Info
(
"checked predeploy storage"
)
if
err
:=
PostCheckUntouchables
(
underlyingDB
,
db
,
prevHeader
.
Root
,
l1ChainID
);
err
!=
nil
{
return
err
}
...
...
@@ -77,6 +134,11 @@ func PostCheckMigratedDB(ldb ethdb.Database, migrationData migration.MigrationDa
}
log
.
Info
(
"checked predeploys"
)
if
err
:=
PostCheckL1Block
(
db
,
info
);
err
!=
nil
{
return
err
}
log
.
Info
(
"checked L1Block"
)
if
err
:=
PostCheckLegacyETH
(
db
);
err
!=
nil
{
return
err
}
...
...
@@ -208,6 +270,63 @@ func PostCheckPredeploys(db *state.StateDB) error {
return
nil
}
// PostCheckPredeployStorage will ensure that the predeploys had their storage
// wiped correctly.
func
PostCheckPredeployStorage
(
db
vm
.
StateDB
,
finalSystemOwner
common
.
Address
)
error
{
for
name
,
addr
:=
range
predeploys
.
Predeploys
{
if
addr
==
nil
{
return
fmt
.
Errorf
(
"nil address in predeploys mapping for %s"
,
name
)
}
// Skip the addresses that did not have their storage reset, also skip the
// L2ToL1MessagePasser because it's already covered by the withdrawals check.
if
FrozenStoragePredeploys
[
*
addr
]
||
*
addr
==
predeploys
.
L2ToL1MessagePasserAddr
||
*
addr
==
predeploys
.
L1BlockAddr
{
continue
}
// Create a mapping of all storage slots. These values were wiped
// so it should not take long to iterate through all of them.
slots
:=
make
(
map
[
common
.
Hash
]
common
.
Hash
)
err
:=
db
.
ForEachStorage
(
*
addr
,
func
(
key
,
value
common
.
Hash
)
bool
{
slots
[
key
]
=
value
return
true
})
if
err
!=
nil
{
return
err
}
log
.
Info
(
"predeploy storage"
,
"name"
,
name
,
"address"
,
*
addr
,
"count"
,
len
(
slots
))
for
key
,
value
:=
range
slots
{
log
.
Debug
(
"storage values"
,
"key"
,
key
.
String
(),
"value"
,
value
.
String
())
}
expSlots
:=
ExpectedStorageSlots
[
*
addr
]
// Assert that the correct number of slots are present.
if
len
(
expSlots
)
!=
len
(
slots
)
{
return
fmt
.
Errorf
(
"expected %d storage slots for %s but got %d"
,
len
(
expSlots
),
name
,
len
(
slots
))
}
for
key
,
value
:=
range
expSlots
{
// The owner slots for the L2XDM and ProxyAdmin are special cases.
// They are set to the final system owner in the config.
if
(
*
addr
==
predeploys
.
L2CrossDomainMessengerAddr
&&
key
==
L2XDMOwnerSlot
)
||
(
*
addr
==
predeploys
.
ProxyAdminAddr
&&
key
==
ProxyAdminOwnerSlot
)
{
actualOwner
:=
common
.
BytesToAddress
(
slots
[
key
]
.
Bytes
())
if
actualOwner
!=
finalSystemOwner
{
return
fmt
.
Errorf
(
"expected owner for %s to be %s but got %s"
,
name
,
finalSystemOwner
,
actualOwner
)
}
log
.
Debug
(
"validated special case owner slot"
,
"value"
,
actualOwner
,
"name"
,
name
)
continue
}
if
slots
[
key
]
!=
value
{
log
.
Debug
(
"validated storage value"
,
"key"
,
key
.
String
(),
"value"
,
value
.
String
())
return
fmt
.
Errorf
(
"expected storage slot %s to be %s but got %s"
,
key
,
value
,
slots
[
key
])
}
}
}
return
nil
}
// PostCheckLegacyETH checks that the legacy eth migration was successful.
// It currently only checks that the total supply was set to 0.
func
PostCheckLegacyETH
(
db
vm
.
StateDB
)
error
{
...
...
@@ -220,6 +339,97 @@ func PostCheckLegacyETH(db vm.StateDB) error {
return
nil
}
// PostCheckL1Block checks that the L1Block contract was properly set to the L1 origin.
func
PostCheckL1Block
(
db
vm
.
StateDB
,
info
*
derive
.
L1BlockInfo
)
error
{
// Slot 0 is the concatenation of the block number and timestamp
data
:=
db
.
GetState
(
predeploys
.
L1BlockAddr
,
common
.
Hash
{})
.
Bytes
()
blockNumber
:=
binary
.
BigEndian
.
Uint64
(
data
[
24
:
])
timestamp
:=
binary
.
BigEndian
.
Uint64
(
data
[
16
:
24
])
if
blockNumber
!=
info
.
Number
{
return
fmt
.
Errorf
(
"expected L1Block block number to be %d, but got %d"
,
info
.
Number
,
blockNumber
)
}
log
.
Debug
(
"validated L1Block block number"
,
"expected"
,
info
.
Number
)
if
timestamp
!=
info
.
Time
{
return
fmt
.
Errorf
(
"expected L1Block timestamp to be %d, but got %d"
,
info
.
Time
,
timestamp
)
}
log
.
Debug
(
"validated L1Block timestamp"
,
"expected"
,
info
.
Time
)
// Slot 1 is the basefee.
baseFee
:=
db
.
GetState
(
predeploys
.
L1BlockAddr
,
common
.
Hash
{
31
:
0x01
})
.
Big
()
if
baseFee
.
Cmp
(
info
.
BaseFee
)
!=
0
{
return
fmt
.
Errorf
(
"expected L1Block basefee to be %s, but got %s"
,
info
.
BaseFee
,
baseFee
)
}
log
.
Debug
(
"validated L1Block basefee"
,
"expected"
,
info
.
BaseFee
)
// Slot 2 is the block hash
hash
:=
db
.
GetState
(
predeploys
.
L1BlockAddr
,
common
.
Hash
{
31
:
0x02
})
if
hash
!=
info
.
BlockHash
{
return
fmt
.
Errorf
(
"expected L1Block hash to be %s, but got %s"
,
info
.
BlockHash
,
hash
)
}
log
.
Debug
(
"validated L1Block hash"
,
"expected"
,
info
.
BlockHash
)
// Slot 3 is the sequence number. It is expected to be zero.
sequenceNumber
:=
db
.
GetState
(
predeploys
.
L1BlockAddr
,
common
.
Hash
{
31
:
0x03
})
expSequenceNumber
:=
common
.
Hash
{}
if
expSequenceNumber
!=
sequenceNumber
{
return
fmt
.
Errorf
(
"expected L1Block sequence number to be %s, but got %s"
,
expSequenceNumber
,
sequenceNumber
)
}
log
.
Debug
(
"validated L1Block sequence number"
,
"expected"
,
expSequenceNumber
)
// Slot 4 is the versioned hash to authenticate the batcher. It is expected to be the initial batch sender.
batcherHash
:=
db
.
GetState
(
predeploys
.
L1BlockAddr
,
common
.
Hash
{
31
:
0x04
})
batchSender
:=
common
.
BytesToAddress
(
batcherHash
.
Bytes
())
if
batchSender
!=
info
.
BatcherAddr
{
return
fmt
.
Errorf
(
"expected L1Block batcherHash to be %s, but got %s"
,
info
.
BatcherAddr
,
batchSender
)
}
log
.
Debug
(
"validated L1Block batcherHash"
,
"expected"
,
info
.
BatcherAddr
)
// Slot 5 is the L1 fee overhead.
l1FeeOverhead
:=
db
.
GetState
(
predeploys
.
L1BlockAddr
,
common
.
Hash
{
31
:
0x05
})
if
!
bytes
.
Equal
(
l1FeeOverhead
.
Bytes
(),
info
.
L1FeeOverhead
[
:
])
{
return
fmt
.
Errorf
(
"expected L1Block L1FeeOverhead to be %s, but got %s"
,
info
.
L1FeeOverhead
,
l1FeeOverhead
)
}
log
.
Debug
(
"validated L1Block L1FeeOverhead"
,
"expected"
,
info
.
L1FeeOverhead
)
// Slot 6 is the L1 fee scalar.
l1FeeScalar
:=
db
.
GetState
(
predeploys
.
L1BlockAddr
,
common
.
Hash
{
31
:
0x06
})
if
!
bytes
.
Equal
(
l1FeeScalar
.
Bytes
(),
info
.
L1FeeScalar
[
:
])
{
return
fmt
.
Errorf
(
"expected L1Block L1FeeScalar to be %s, but got %s"
,
info
.
L1FeeScalar
,
l1FeeScalar
)
}
log
.
Debug
(
"validated L1Block L1FeeScalar"
,
"expected"
,
info
.
L1FeeScalar
)
// Check EIP-1967
proxyAdmin
:=
common
.
BytesToAddress
(
db
.
GetState
(
predeploys
.
L1BlockAddr
,
AdminSlot
)
.
Bytes
())
if
proxyAdmin
!=
predeploys
.
ProxyAdminAddr
{
return
fmt
.
Errorf
(
"expected L1Block admin to be %s, but got %s"
,
predeploys
.
ProxyAdminAddr
,
proxyAdmin
)
}
log
.
Debug
(
"validated L1Block admin"
,
"expected"
,
predeploys
.
ProxyAdminAddr
)
expImplementation
,
err
:=
AddressToCodeNamespace
(
predeploys
.
L1BlockAddr
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to get expected implementation for L1Block: %w"
,
err
)
}
actImplementation
:=
common
.
BytesToAddress
(
db
.
GetState
(
predeploys
.
L1BlockAddr
,
ImplementationSlot
)
.
Bytes
())
if
expImplementation
!=
actImplementation
{
return
fmt
.
Errorf
(
"expected L1Block implementation to be %s, but got %s"
,
expImplementation
,
actImplementation
)
}
log
.
Debug
(
"validated L1Block implementation"
,
"expected"
,
expImplementation
)
var
count
int
err
=
db
.
ForEachStorage
(
predeploys
.
L1BlockAddr
,
func
(
key
,
value
common
.
Hash
)
bool
{
count
++
return
true
})
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to iterate over L1Block storage: %w"
,
err
)
}
if
count
!=
8
{
return
fmt
.
Errorf
(
"expected L1Block to have 8 storage slots, but got %d"
,
count
)
}
log
.
Debug
(
"validated L1Block storage slot count"
,
"expected"
,
8
)
return
nil
}
func
CheckWithdrawalsAfter
(
db
vm
.
StateDB
,
data
migration
.
MigrationData
,
l1CrossDomainMessenger
*
common
.
Address
)
error
{
wds
,
err
:=
data
.
ToWithdrawals
()
if
err
!=
nil
{
...
...
@@ -289,3 +499,14 @@ func CheckWithdrawalsAfter(db vm.StateDB, data migration.MigrationData, l1CrossD
}
return
nil
}
func
eip1967Slots
(
address
common
.
Address
)
StorageCheckMap
{
codeAddr
,
err
:=
AddressToCodeNamespace
(
address
)
if
err
!=
nil
{
panic
(
err
)
}
return
StorageCheckMap
{
AdminSlot
:
predeploys
.
ProxyAdminAddr
.
Hash
(),
ImplementationSlot
:
codeAddr
.
Hash
(),
}
}
op-chain-ops/genesis/db_migration.go
View file @
31532ce1
...
...
@@ -33,18 +33,29 @@ type MigrationResult struct {
TransitionBlockHash
common
.
Hash
}
// MigrateDB will migrate an
old l2geth database to the new bedrock style system
// MigrateDB will migrate an
l2geth legacy Optimism database to a Bedrock database.
func
MigrateDB
(
ldb
ethdb
.
Database
,
config
*
DeployConfig
,
l1Block
*
types
.
Block
,
migrationData
*
migration
.
MigrationData
,
commit
,
noCheck
bool
)
(
*
MigrationResult
,
error
)
{
// Grab the hash of the tip of the legacy chain.
hash
:=
rawdb
.
ReadHeadHeaderHash
(
ldb
)
log
.
Info
(
"Reading chain tip from database"
,
"hash"
,
hash
)
// Grab the header number.
num
:=
rawdb
.
ReadHeaderNumber
(
ldb
,
hash
)
if
num
==
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot find header number for %s"
,
hash
)
}
// Grab the full header.
header
:=
rawdb
.
ReadHeader
(
ldb
,
hash
,
*
num
)
log
.
Info
(
"Read header from database"
,
"number"
,
*
num
)
// Ensure that the extradata is valid.
if
size
:=
len
(
BedrockTransitionBlockExtraData
);
size
>
32
{
return
nil
,
fmt
.
Errorf
(
"transition block extradata too long: %d"
,
size
)
}
// We write special extra data into the Bedrock transition block to indicate that the migration
// has already happened. If we detect this extra data, we can skip the migration.
if
bytes
.
Equal
(
header
.
Extra
,
BedrockTransitionBlockExtraData
)
{
log
.
Info
(
"Detected migration already happened"
,
"root"
,
header
.
Root
,
"blockhash"
,
header
.
Hash
())
...
...
@@ -55,103 +66,147 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m
},
nil
}
// Ensure monotonic timestamps
// Ensure that the timestamp for the Bedrock transition block is greater than the timestamp of
// the last legacy block.
if
uint64
(
config
.
L2OutputOracleStartingTimestamp
)
<=
header
.
Time
{
return
nil
,
fmt
.
Errorf
(
"
L2
output oracle starting timestamp (%d) is less than the header timestamp (%d)"
,
config
.
L2OutputOracleStartingTimestamp
,
header
.
Time
,
"output oracle starting timestamp (%d) is less than the header timestamp (%d)"
,
config
.
L2OutputOracleStartingTimestamp
,
header
.
Time
,
)
}
// Ensure that the starting timestamp is safe
// Ensure that the timestamp for the Bedrock transition block is greater than 0, not implicitly
// guaranteed by the above check because the above converted the timestamp to a uint64.
if
config
.
L2OutputOracleStartingTimestamp
<=
0
{
return
nil
,
fmt
.
Errorf
(
"
L2
output oracle starting timestamp (%d) cannot be <= 0"
,
config
.
L2OutputOracleStartingTimestamp
,
"output oracle starting timestamp (%d) cannot be <= 0"
,
config
.
L2OutputOracleStartingTimestamp
,
)
}
// Set up the backing store.
underlyingDB
:=
state
.
NewDatabaseWithConfig
(
ldb
,
&
trie
.
Config
{
Preimages
:
true
,
Cache
:
1024
,
})
// Open up the state database.
db
,
err
:=
state
.
New
(
header
.
Root
,
underlyingDB
,
nil
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot open StateDB: %w"
,
err
)
}
// Convert all of the messages into legacy withdrawals
// 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
// witness data for the migration. We operate under the assumption that the witness data is
// untrusted and must be verified explicitly before we can use it.
// Generate and verify the configuration for storage variables to be set on L2.
storage
,
err
:=
NewL2StorageConfig
(
config
,
l1Block
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot create storage config: %w"
,
err
)
}
// Generate and verify the configuration for immutable variables to be set on L2.
immutable
,
err
:=
NewL2ImmutableConfig
(
config
,
l1Block
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot create immutable config: %w"
,
err
)
}
// Convert all input messages into legacy messages. Note that this list is not yet filtered and
// may be missing some messages or have some extra messages.
unfilteredWithdrawals
,
err
:=
migrationData
.
ToWithdrawals
()
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot serialize withdrawals: %w"
,
err
)
}
// We now need to check that we have all of the withdrawals that we expect to have. An error
// will be thrown if there are any missing messages, and any extra messages will be removed.
var
filteredWithdrawals
[]
*
crossdomain
.
LegacyWithdrawal
if
!
noCheck
{
log
.
Info
(
"Checking withdrawals..."
)
filteredWithdrawals
,
err
=
PreCheckWithdrawals
(
db
,
unfilteredWithdrawals
)
filteredWithdrawals
,
err
=
crossdomain
.
PreCheckWithdrawals
(
db
,
unfilteredWithdrawals
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"withdrawals mismatch: %w"
,
err
)
}
log
.
Info
(
"Withdrawals accounted for!"
)
}
else
{
log
.
Info
(
"Skipping checking withdrawals"
)
filteredWithdrawals
=
unfilteredWithdrawals
}
// Now start the migration
log
.
Info
(
"Setting the Proxies"
)
if
err
:=
SetL2Proxies
(
db
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot set L2Proxies: %w"
,
err
)
// We also need to verify that we have all of the storage slots for the LegacyERC20ETH contract
// that we expect to have. An error will be thrown if there are any missing storage slots.
// 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.
log
.
Info
(
"Checking addresses..."
,
"no-check"
,
noCheck
)
addrs
,
err
:=
ether
.
PreCheckBalances
(
ldb
,
db
,
migrationData
.
Addresses
(),
migrationData
.
OvmAllowances
,
int
(
config
.
L1ChainID
),
noCheck
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"addresses mismatch: %w"
,
err
)
}
storage
,
err
:=
NewL2StorageConfig
(
config
,
l1Block
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot create storage config: %w"
,
err
)
// At this point we've fully verified the witness data for the migration, so we can begin the
// actual migration process. This involves modifying parts of the legacy database and inserting
// a transition block.
// We need to wipe the storage of every predeployed contract EXCEPT for the GovernanceToken,
// WETH9, the DeployerWhitelist, the LegacyMessagePasser, and LegacyERC20ETH. We have verified
// that none of the legacy storage (other than the aforementioned contracts) is accessible and
// therefore can be safely removed from the database. Storage must be wiped before anything
// else or the ERC-1967 proxy storage slots will be removed.
if
err
:=
WipePredeployStorage
(
db
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot wipe storage: %w"
,
err
)
}
immutable
,
err
:=
NewL2ImmutableConfig
(
config
,
l1Block
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot create immutable config: %w"
,
err
)
// Next order of business is to convert all predeployed smart contracts into proxies so they
// can be easily upgraded later on. In the legacy system, all upgrades to predeployed contracts
// required hard forks which was a huge pain. Note that we do NOT put the GovernanceToken or
// WETH9 contracts behind proxies because we do not want to make these easily upgradable.
log
.
Info
(
"Converting predeployed contracts to proxies"
)
if
err
:=
SetL2Proxies
(
db
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot set L2Proxies: %w"
,
err
)
}
// Here we update the storage of each predeploy with the new storage variables that we want to
// set on L2 and update the implementations for all predeployed contracts that are behind
// proxies (NOT the GovernanceToken or WETH9).
log
.
Info
(
"Updating implementations for predeployed contracts"
)
if
err
:=
SetImplementations
(
db
,
storage
,
immutable
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot set implementations: %w"
,
err
)
}
// We need to update the code for LegacyERC20ETH. This is NOT a standard predeploy because it's
// deployed at the 0xdeaddeaddead... address and therefore won't be updated by the previous
// function call to SetImplementations.
log
.
Info
(
"Updating code for LegacyERC20ETH"
)
if
err
:=
SetLegacyETH
(
db
,
storage
,
immutable
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot set legacy ETH: %w"
,
err
)
}
// Now we migrate legacy withdrawals from the LegacyMessagePasser contract to their new format
// in the Bedrock L2ToL1MessagePasser contract. Note that we do NOT delete the withdrawals from
// the LegacyMessagePasser contract. Here we operate on the list of withdrawals that we
// previously filtered and verified.
log
.
Info
(
"Starting to migrate withdrawals"
,
"no-check"
,
noCheck
)
err
=
crossdomain
.
MigrateWithdrawals
(
filteredWithdrawals
,
db
,
&
config
.
L1CrossDomainMessengerProxy
,
noCheck
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot migrate withdrawals: %w"
,
err
)
}
log
.
Info
(
"Completed withdrawal migration"
)
// Finally we migrate the balances held inside the LegacyERC20ETH contract into the state trie.
// Note that we do NOT delete the balances from the LegacyERC20ETH contract.
log
.
Info
(
"Starting to migrate ERC20 ETH"
)
addrs
:=
migrationData
.
Addresses
()
err
=
ether
.
MigrateLegacyETH
(
ldb
,
db
,
addrs
,
migrationData
.
OvmAllowances
,
int
(
config
.
L1ChainID
),
noCheck
)
err
=
ether
.
MigrateLegacyETH
(
ldb
,
db
,
addrs
,
int
(
config
.
L1ChainID
),
noCheck
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot migrate legacy eth: %w"
,
err
)
}
log
.
Info
(
"Completed ERC20 ETH migration"
)
// We're done messing around with the database, so we can now commit the changes to the DB.
// Note that this doesn't actually write the changes to disk.
log
.
Info
(
"Committing state DB"
)
newRoot
,
err
:=
db
.
Commit
(
true
)
if
err
!=
nil
{
return
nil
,
err
}
log
.
Info
(
"committed state DB"
,
"root"
,
newRoot
)
// Set the amount of gas used so that EIP 1559 starts off stable
gasUsed
:=
(
uint64
)(
config
.
L2GenesisBlockGasLimit
)
*
config
.
EIP1559Elasticity
// Ensure that the extradata is valid
if
size
:=
len
(
BedrockTransitionBlockExtraData
);
size
>
32
{
return
nil
,
fmt
.
Errorf
(
"transition block extradata too long: %d"
,
size
)
}
// Create the bedrock transition block
// Create the header for the Bedrock transition block.
bedrockHeader
:=
&
types
.
Header
{
ParentHash
:
header
.
Hash
(),
UncleHash
:
types
.
EmptyUncleHash
,
...
...
@@ -163,7 +218,7 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m
Difficulty
:
common
.
Big0
,
Number
:
new
(
big
.
Int
)
.
Add
(
header
.
Number
,
common
.
Big1
),
GasLimit
:
(
uint64
)(
config
.
L2GenesisBlockGasLimit
),
GasUsed
:
gasUsed
,
GasUsed
:
0
,
Time
:
uint64
(
config
.
L2OutputOracleStartingTimestamp
),
Extra
:
BedrockTransitionBlockExtraData
,
MixDigest
:
common
.
Hash
{},
...
...
@@ -171,8 +226,11 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m
BaseFee
:
big
.
NewInt
(
params
.
InitialBaseFee
),
}
// Create the Bedrock transition block from the header. Note that there are no transactions,
// uncle blocks, or receipts in the Bedrock transition block.
bedrockBlock
:=
types
.
NewBlock
(
bedrockHeader
,
nil
,
nil
,
nil
,
trie
.
NewStackTrie
(
nil
))
// We did it!
log
.
Info
(
"Built Bedrock transition"
,
"hash"
,
bedrockBlock
.
Hash
(),
...
...
@@ -182,22 +240,26 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m
"gas-limit"
,
bedrockBlock
.
GasLimit
(),
)
// Create the result of the migration.
res
:=
&
MigrationResult
{
TransitionHeight
:
bedrockBlock
.
NumberU64
(),
TransitionTimestamp
:
bedrockBlock
.
Time
(),
TransitionBlockHash
:
bedrockBlock
.
Hash
(),
}
// If we're not actually writing this to disk, then we're done.
if
!
commit
{
log
.
Info
(
"Dry run complete"
)
return
res
,
nil
}
log
.
Info
(
"committing trie DB"
)
// Otherwise we need to write the changes to disk. First we commit the state changes.
log
.
Info
(
"Committing trie DB"
)
if
err
:=
db
.
Database
()
.
TrieDB
()
.
Commit
(
newRoot
,
true
,
nil
);
err
!=
nil
{
return
nil
,
err
}
// Next we write the Bedrock transition block to the database.
rawdb
.
WriteTd
(
ldb
,
bedrockBlock
.
Hash
(),
bedrockBlock
.
NumberU64
(),
bedrockBlock
.
Difficulty
())
rawdb
.
WriteBlock
(
ldb
,
bedrockBlock
)
rawdb
.
WriteReceipts
(
ldb
,
bedrockBlock
.
Hash
(),
bedrockBlock
.
NumberU64
(),
nil
)
...
...
@@ -209,32 +271,39 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m
// Make the first Bedrock block a finalized block.
rawdb
.
WriteFinalizedBlockHash
(
ldb
,
bedrockBlock
.
Hash
())
// We need to pull the chain config out of the DB, and update
// it so that the latest hardforks are enabled.
// We need to update the chain config to set the correct hardforks.
genesisHash
:=
rawdb
.
ReadCanonicalHash
(
ldb
,
0
)
cfg
:=
rawdb
.
ReadChainConfig
(
ldb
,
genesisHash
)
if
cfg
==
nil
{
log
.
Crit
(
"chain config not found"
)
}
// Set the standard options.
cfg
.
LondonBlock
=
bedrockBlock
.
Number
()
cfg
.
ArrowGlacierBlock
=
bedrockBlock
.
Number
()
cfg
.
GrayGlacierBlock
=
bedrockBlock
.
Number
()
cfg
.
MergeNetsplitBlock
=
bedrockBlock
.
Number
()
cfg
.
TerminalTotalDifficulty
=
big
.
NewInt
(
0
)
cfg
.
TerminalTotalDifficultyPassed
=
true
// Set the Optimism options.
cfg
.
BedrockBlock
=
bedrockBlock
.
Number
()
cfg
.
Optimism
=
&
params
.
OptimismConfig
{
EIP1559Denominator
:
config
.
EIP1559Denominator
,
EIP1559Elasticity
:
config
.
EIP1559Elasticity
,
}
cfg
.
BedrockBlock
=
bedrockBlock
.
Number
()
// Write the chain config to disk.
rawdb
.
WriteChainConfig
(
ldb
,
genesisHash
,
cfg
)
// Yay!
log
.
Info
(
"wrote chain config"
,
"1559-denominator"
,
config
.
EIP1559Denominator
,
"1559-elasticity"
,
config
.
EIP1559Elasticity
,
)
// We're done!
log
.
Info
(
"wrote Bedrock transition block"
,
"height"
,
bedrockHeader
.
Number
,
...
...
@@ -243,63 +312,6 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m
"timestamp"
,
bedrockHeader
.
Time
,
)
// Return the result and have a nice day.
return
res
,
nil
}
// PreCheckWithdrawals will ensure that the entire list of withdrawals is being
// operated on during the database migration.
func
PreCheckWithdrawals
(
db
*
state
.
StateDB
,
withdrawals
[]
*
crossdomain
.
LegacyWithdrawal
)
([]
*
crossdomain
.
LegacyWithdrawal
,
error
)
{
// Create a mapping of all of their storage slots
slotsWds
:=
make
(
map
[
common
.
Hash
]
*
crossdomain
.
LegacyWithdrawal
)
for
_
,
wd
:=
range
withdrawals
{
slot
,
err
:=
wd
.
StorageSlot
()
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot check withdrawals: %w"
,
err
)
}
slotsWds
[
slot
]
=
wd
}
// Build a map of all the slots in the LegacyMessagePasser
var
count
int
slots
:=
make
(
map
[
common
.
Hash
]
bool
)
err
:=
db
.
ForEachStorage
(
predeploys
.
LegacyMessagePasserAddr
,
func
(
key
,
value
common
.
Hash
)
bool
{
if
value
!=
abiTrue
{
return
false
}
slots
[
key
]
=
true
count
++
return
true
})
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot iterate over LegacyMessagePasser: %w"
,
err
)
}
log
.
Info
(
"iterated legacy messages"
,
"count"
,
count
)
// Check that all of the slots from storage correspond to a known message
for
slot
:=
range
slots
{
_
,
ok
:=
slotsWds
[
slot
]
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"Unknown storage slot in state: %s"
,
slot
)
}
}
filtered
:=
make
([]
*
crossdomain
.
LegacyWithdrawal
,
0
)
// Check that all of the input messages are legit
for
slot
:=
range
slotsWds
{
//nolint:staticcheck
_
,
ok
:=
slots
[
slot
]
//nolint:staticcheck
if
!
ok
{
log
.
Info
(
"filtering out unknown input message"
,
"slot"
,
slot
.
String
())
continue
}
filtered
=
append
(
filtered
,
slotsWds
[
slot
])
}
return
filtered
,
nil
}
op-chain-ops/genesis/setters.go
View file @
31532ce1
...
...
@@ -14,18 +14,21 @@ import (
"github.com/ethereum/go-ethereum/log"
)
// UntouchablePredeploys are addresses in the predeploy namespace
// that should not be touched by the migration process.
var
UntouchablePredeploys
=
map
[
common
.
Address
]
bool
{
predeploys
.
GovernanceTokenAddr
:
true
,
predeploys
.
WETH9Addr
:
true
,
}
// UntouchableCodeHashes contains code hashes of all the contracts
// that should not be touched by the migration process.
type
ChainHashMap
map
[
uint64
]
common
.
Hash
var
UntouchableCodeHashes
=
map
[
common
.
Address
]
ChainHashMap
{
var
(
// UntouchablePredeploys are addresses in the predeploy namespace
// that should not be touched by the migration process.
UntouchablePredeploys
=
map
[
common
.
Address
]
bool
{
predeploys
.
GovernanceTokenAddr
:
true
,
predeploys
.
WETH9Addr
:
true
,
}
// UntouchableCodeHashes represent the bytecode hashes of contracts
// that should not be touched by the migration process.
UntouchableCodeHashes
=
map
[
common
.
Address
]
ChainHashMap
{
predeploys
.
GovernanceTokenAddr
:
{
1
:
common
.
HexToHash
(
"0x8551d935f4e67ad3c98609f0d9f0f234740c4c4599f82674633b55204393e07f"
),
5
:
common
.
HexToHash
(
"0xc4a213cf5f06418533e5168d8d82f7ccbcc97f27ab90197c2c051af6a4941cf9"
),
...
...
@@ -34,7 +37,22 @@ var UntouchableCodeHashes = map[common.Address]ChainHashMap{
1
:
common
.
HexToHash
(
"0x779bbf2a738ef09d961c945116197e2ac764c1b39304b2b4418cd4e42668b173"
),
5
:
common
.
HexToHash
(
"0x779bbf2a738ef09d961c945116197e2ac764c1b39304b2b4418cd4e42668b173"
),
},
}
}
// FrozenStoragePredeploys represents the set of predeploys that
// will not have their storage wiped during the migration process.
// It is very explicitly set in its own mapping to ensure that
// changes elsewhere in the codebase do no alter the predeploys
// that do not have their storage wiped. It is safe for all other
// predeploys to have their storage wiped.
FrozenStoragePredeploys
=
map
[
common
.
Address
]
bool
{
predeploys
.
GovernanceTokenAddr
:
true
,
predeploys
.
WETH9Addr
:
true
,
predeploys
.
LegacyMessagePasserAddr
:
true
,
predeploys
.
LegacyERC20ETHAddr
:
true
,
predeploys
.
DeployerWhitelistAddr
:
true
,
}
)
// FundDevAccounts will fund each of the development accounts.
func
FundDevAccounts
(
db
vm
.
StateDB
)
{
...
...
@@ -60,6 +78,26 @@ func SetL1Proxies(db vm.StateDB, proxyAdminAddr common.Address) error {
return
setProxies
(
db
,
proxyAdminAddr
,
bigL1PredeployNamespace
,
2048
)
}
// WipePredeployStorage will wipe the storage of all L2 predeploys expect
// for predeploys that must not have their storage altered.
func
WipePredeployStorage
(
db
vm
.
StateDB
)
error
{
for
name
,
addr
:=
range
predeploys
.
Predeploys
{
if
addr
==
nil
{
return
fmt
.
Errorf
(
"nil address in predeploys mapping for %s"
,
name
)
}
if
FrozenStoragePredeploys
[
*
addr
]
{
log
.
Trace
(
"skipping wiping of storage"
,
"name"
,
name
,
"address"
,
*
addr
)
continue
}
log
.
Info
(
"wiping storage"
,
"name"
,
name
,
"address"
,
*
addr
)
db
.
CreateAccount
(
*
addr
)
}
return
nil
}
func
setProxies
(
db
vm
.
StateDB
,
proxyAdminAddr
common
.
Address
,
namespace
*
big
.
Int
,
count
uint64
)
error
{
depBytecode
,
err
:=
bindings
.
GetDeployedBytecode
(
"Proxy"
)
if
err
!=
nil
{
...
...
op-chain-ops/go.mod
View file @
31532ce1
...
...
@@ -29,6 +29,8 @@ require (
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
...
...
op-chain-ops/go.sum
View file @
31532ce1
...
...
@@ -24,8 +24,10 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/btcsuite/btcd v0.23.3 h1:4KH/JKy9WiCd+iUS9Mu0Zp7Dnj17TGdKrg9xc/FGj24=
...
...
@@ -81,6 +83,7 @@ github.com/ethereum-optimism/optimism/op-bindings v0.10.6 h1:p+DyvdgM84Ub1Q2ihhj
github.com/ethereum-optimism/optimism/op-bindings v0.10.6/go.mod h1:9ZSUq/rjlzp3uYyBN4sZmhTc3oZgDVqJ4wrUja7vj6c=
github.com/ethereum-optimism/optimism/op-node v0.10.1 h1:kVBaOEOYLV22XEHRhB7dfdmoXepO0kx/RsZQK+Bpk1Y=
github.com/ethereum-optimism/optimism/op-node v0.10.1/go.mod h1:pup7wiiUs9g8cZKwXeB5tEGCqwUUwFVmej9MmSIm6S8=
github.com/ethereum-optimism/optimism/op-service v0.10.1 h1:s8CisVat3ia04Z0mW3IiwZ7V1EInyVe3ODq6UXSyJG4=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
...
...
@@ -110,6 +113,7 @@ github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFG
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
...
...
@@ -125,6 +129,7 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
...
...
@@ -157,11 +162,15 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
...
...
@@ -189,6 +198,7 @@ github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/ipfs/go-cid v0.3.2 h1:OGgOd+JCFM+y1DjWPmVH+2/4POtpDzwcr7VgnB7mZXc=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
...
...
@@ -199,6 +209,7 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
...
...
@@ -209,6 +220,11 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
github.com/libp2p/go-libp2p v0.23.3 h1:/n3i0VtJF0iZ9YMUxl/teOY3h+M8NfgaCjOSYr9D+uI=
github.com/libp2p/go-libp2p-pubsub v0.8.1 h1:hSw09NauFUaA0FLgQPBJp6QOy0a2n+HSkb8IeOx8OnY=
github.com/libp2p/go-openssl v0.1.0 h1:LBkKEcUv6vtZIQLVTegAil8jbNpJErQ9AnT+bWV+Ooo=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
...
...
@@ -218,12 +234,15 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
...
...
@@ -237,6 +256,14 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4=
github.com/multiformats/go-multiaddr v0.7.0 h1:gskHcdaCyPtp9XskVwtvEeQOG465sCohbQIirSyqxrc=
github.com/multiformats/go-multibase v0.1.1 h1:3ASCDsuLX8+j4kx58qnJ4YFq/JWTJpCyDW27ztsVTOI=
github.com/multiformats/go-multicodec v0.6.0 h1:KhH2kSuCARyuJraYMFxrNO3DqIaYhOdS039kbhgVwpE=
github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108=
github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
...
...
@@ -295,18 +322,22 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic=
github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
...
...
@@ -336,7 +367,9 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg=
...
...
@@ -346,6 +379,7 @@ github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5J
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
...
...
@@ -532,6 +566,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
...
...
@@ -561,5 +596,6 @@ honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
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