2019-12-19 18:46:30 +00:00
package stmgr
import (
2020-09-24 21:30:11 +00:00
"bytes"
2019-12-19 18:46:30 +00:00
"context"
2020-09-24 21:30:11 +00:00
"encoding/binary"
2021-01-27 23:47:34 +00:00
"runtime"
2021-01-26 20:46:57 +00:00
"sort"
2021-01-26 23:11:31 +00:00
"sync"
2021-01-27 23:05:00 +00:00
"time"
2020-09-24 21:30:11 +00:00
2021-01-19 07:34:08 +00:00
"github.com/filecoin-project/go-state-types/rt"
2020-09-05 03:01:36 +00:00
"github.com/filecoin-project/go-address"
2020-09-07 03:49:10 +00:00
"github.com/filecoin-project/go-state-types/abi"
2020-09-05 03:01:36 +00:00
"github.com/filecoin-project/go-state-types/big"
2020-10-01 22:02:40 +00:00
"github.com/filecoin-project/go-state-types/network"
2020-09-05 03:01:36 +00:00
"github.com/filecoin-project/lotus/build"
2020-09-28 22:54:48 +00:00
"github.com/filecoin-project/lotus/chain/actors/adt"
2020-11-19 06:47:13 +00:00
"github.com/filecoin-project/lotus/chain/actors/builtin"
2020-09-28 22:54:48 +00:00
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
2020-09-28 21:25:58 +00:00
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/state"
2020-10-07 12:10:23 +00:00
"github.com/filecoin-project/lotus/chain/store"
2020-07-28 12:31:13 +00:00
"github.com/filecoin-project/lotus/chain/types"
2020-09-24 21:30:11 +00:00
"github.com/filecoin-project/lotus/chain/vm"
2020-10-07 12:10:23 +00:00
bstore "github.com/filecoin-project/lotus/lib/blockstore"
"github.com/filecoin-project/lotus/lib/bufbstore"
2020-11-19 06:47:13 +00:00
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
multisig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/migration/nv3"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/specs-actors/v2/actors/migration/nv4"
"github.com/filecoin-project/specs-actors/v2/actors/migration/nv7"
2021-01-19 16:48:10 +00:00
"github.com/filecoin-project/specs-actors/v3/actors/migration/nv10"
2020-11-19 06:47:13 +00:00
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
"golang.org/x/xerrors"
2019-12-19 18:46:30 +00:00
)
2021-01-26 20:46:57 +00:00
// MigrationCache can be used to cache information used by a migration. This is primarily useful to
// "pre-compute" some migration state ahead of time, and make it accessible in the migration itself.
type MigrationCache interface {
Write ( key string , value cid . Cid ) error
Read ( key string ) ( bool , cid . Cid , error )
Load ( key string , loadFunc func ( ) ( cid . Cid , error ) ) ( cid . Cid , error )
}
2021-01-26 23:15:14 +00:00
// MigrationFunc is a migration function run at every upgrade.
2020-10-07 20:56:38 +00:00
//
2021-01-26 20:46:57 +00:00
// - The cache is a per-upgrade cache, pre-populated by pre-migrations.
2020-10-07 20:56:38 +00:00
// - The oldState is the state produced by the upgrade epoch.
// - The returned newState is the new state that will be used by the next epoch.
// - The height is the upgrade epoch height (already executed).
// - The tipset is the tipset for the last non-null block before the upgrade. Do
// not assume that ts.Height() is the upgrade height.
2021-01-26 23:15:14 +00:00
type MigrationFunc func (
2021-01-26 20:46:57 +00:00
ctx context . Context ,
sm * StateManager , cache MigrationCache ,
cb ExecCallback , oldState cid . Cid ,
height abi . ChainEpoch , ts * types . TipSet ,
) ( newState cid . Cid , err error )
2021-01-26 23:15:14 +00:00
// PreMigrationFunc is a function run _before_ a network upgrade to pre-compute part of the network
2021-01-26 20:46:57 +00:00
// upgrade and speed it up.
2021-01-26 23:15:14 +00:00
type PreMigrationFunc func (
2021-01-26 20:46:57 +00:00
ctx context . Context ,
sm * StateManager , cache MigrationCache ,
oldState cid . Cid ,
height abi . ChainEpoch , ts * types . TipSet ,
2021-01-26 22:57:38 +00:00
) error
2021-01-26 20:46:57 +00:00
2021-01-26 23:15:14 +00:00
// PreMigration describes a pre-migration step to prepare for a network state upgrade. Pre-migrations
2021-01-26 20:46:57 +00:00
// are optimizations, are not guaranteed to run, and may be canceled and/or run multiple times.
2021-01-26 23:15:14 +00:00
type PreMigration struct {
// PreMigration is the pre-migration function to run at the specified time. This function is
2021-01-26 23:05:12 +00:00
// run asynchronously and must abort promptly when canceled.
2021-01-26 23:15:14 +00:00
PreMigration PreMigrationFunc
2021-01-26 20:46:57 +00:00
2021-01-27 23:58:51 +00:00
// StartWithin specifies that this pre-migration should be started at most StartWithin
// epochs before the upgrade.
StartWithin abi . ChainEpoch
2021-01-26 20:46:57 +00:00
2021-01-27 23:58:51 +00:00
// DontStartWithin specifies that this pre-migration should not be started DontStartWithin
// epochs before the final upgrade epoch.
2021-01-26 20:46:57 +00:00
//
2021-01-27 23:58:51 +00:00
// This should be set such that the pre-migration is likely to complete before StopWithin.
DontStartWithin abi . ChainEpoch
// StopWithin specifies that this pre-migration should be stopped StopWithin epochs of the
// final upgrade epoch.
StopWithin abi . ChainEpoch
2021-01-26 20:46:57 +00:00
}
2020-10-01 22:02:40 +00:00
type Upgrade struct {
Height abi . ChainEpoch
2020-10-03 00:09:56 +00:00
Network network . Version
2020-10-07 23:14:11 +00:00
Expensive bool
2021-01-26 23:15:14 +00:00
Migration MigrationFunc
2021-01-26 20:46:57 +00:00
2021-01-26 23:15:14 +00:00
// PreMigrations specifies a set of pre-migration functions to run at the indicated epochs.
2021-01-26 20:46:57 +00:00
// These functions should fill the given cache with information that can speed up the
// eventual full migration at the upgrade epoch.
2021-01-26 23:15:14 +00:00
PreMigrations [ ] PreMigration
2020-10-01 22:02:40 +00:00
}
2020-10-03 00:09:56 +00:00
type UpgradeSchedule [ ] Upgrade
2020-10-01 22:02:40 +00:00
2021-01-19 07:34:08 +00:00
type migrationLogger struct { }
func ( ml migrationLogger ) Log ( level rt . LogLevel , msg string , args ... interface { } ) {
switch level {
case rt . DEBUG :
log . Debugf ( msg , args ... )
case rt . INFO :
log . Infof ( msg , args ... )
case rt . WARN :
log . Warnf ( msg , args ... )
case rt . ERROR :
log . Errorf ( msg , args ... )
}
}
2020-10-03 00:09:56 +00:00
func DefaultUpgradeSchedule ( ) UpgradeSchedule {
var us UpgradeSchedule
2020-10-07 22:17:24 +00:00
updates := [ ] Upgrade { {
2020-10-03 00:09:56 +00:00
Height : build . UpgradeBreezeHeight ,
Network : network . Version1 ,
Migration : UpgradeFaucetBurnRecovery ,
} , {
Height : build . UpgradeSmokeHeight ,
Network : network . Version2 ,
Migration : nil ,
} , {
Height : build . UpgradeIgnitionHeight ,
Network : network . Version3 ,
Migration : UpgradeIgnition ,
2020-10-06 21:47:03 +00:00
} , {
Height : build . UpgradeRefuelHeight ,
Network : network . Version3 ,
Migration : UpgradeRefuel ,
2020-10-03 00:09:56 +00:00
} , {
Height : build . UpgradeActorsV2Height ,
Network : network . Version4 ,
2020-10-07 23:14:11 +00:00
Expensive : true ,
2020-10-03 00:09:56 +00:00
Migration : UpgradeActorsV2 ,
2020-10-12 05:31:46 +00:00
} , {
2020-11-19 06:47:13 +00:00
Height : build . UpgradeTapeHeight ,
Network : network . Version5 ,
Migration : nil ,
2020-10-03 00:09:56 +00:00
} , {
Height : build . UpgradeLiftoffHeight ,
2020-10-12 05:31:46 +00:00
Network : network . Version5 ,
2020-10-03 00:09:56 +00:00
Migration : UpgradeLiftoff ,
2020-10-17 00:35:46 +00:00
} , {
Height : build . UpgradeKumquatHeight ,
Network : network . Version6 ,
Migration : nil ,
2020-11-08 04:05:52 +00:00
} , {
Height : build . UpgradeCalicoHeight ,
Network : network . Version7 ,
Migration : UpgradeCalico ,
2020-11-06 02:33:39 +00:00
} , {
Height : build . UpgradePersianHeight ,
Network : network . Version8 ,
Migration : nil ,
2020-12-19 19:44:16 +00:00
} , {
Height : build . UpgradeOrangeHeight ,
Network : network . Version9 ,
Migration : nil ,
2021-01-19 03:42:23 +00:00
} , {
Height : build . UpgradeActorsV3Height ,
Network : network . Version10 ,
Migration : UpgradeActorsV3 ,
2021-01-26 23:15:14 +00:00
PreMigrations : [ ] PreMigration { {
2021-01-27 23:58:51 +00:00
PreMigration : PreUpgradeActorsV3 ,
StartWithin : 120 ,
DontStartWithin : 60 ,
StopWithin : 35 ,
2021-01-26 22:57:38 +00:00
} , {
2021-01-27 23:58:51 +00:00
PreMigration : PreUpgradeActorsV3 ,
StartWithin : 30 ,
DontStartWithin : 15 ,
StopWithin : 5 ,
2021-01-26 22:57:38 +00:00
} } ,
2021-01-20 02:31:50 +00:00
Expensive : true ,
2020-10-07 22:17:24 +00:00
} }
for _ , u := range updates {
2020-10-03 00:09:56 +00:00
if u . Height < 0 {
// upgrade disabled
continue
}
us = append ( us , u )
}
return us
}
func ( us UpgradeSchedule ) Validate ( ) error {
2021-01-26 23:00:55 +00:00
// Make sure each upgrade is valid.
2020-10-03 00:09:56 +00:00
for _ , u := range us {
if u . Network <= 0 {
return xerrors . Errorf ( "cannot upgrade to version <= 0: %d" , u . Network )
}
2021-01-26 23:00:55 +00:00
2021-01-26 23:15:14 +00:00
for _ , m := range u . PreMigrations {
2021-01-27 23:58:51 +00:00
if m . StartWithin <= 0 {
return xerrors . Errorf ( "pre-migration must specify a positive start-within epoch" )
}
if m . DontStartWithin < 0 || m . StopWithin < 0 {
2021-01-27 20:24:48 +00:00
return xerrors . Errorf ( "pre-migration must specify non-negative epochs" )
}
2021-01-27 23:58:51 +00:00
if m . StartWithin <= m . StopWithin {
return xerrors . Errorf ( "pre-migration start-within must come before stop-within" )
}
// If we have a dont-start-within.
if m . DontStartWithin != 0 {
if m . DontStartWithin < m . StopWithin {
return xerrors . Errorf ( "pre-migration dont-start-within must come before stop-within" )
}
if m . StartWithin <= m . DontStartWithin {
return xerrors . Errorf ( "pre-migration start-within must come after dont-start-within" )
}
2021-01-26 23:00:55 +00:00
}
}
2021-01-27 20:24:48 +00:00
if ! sort . SliceIsSorted ( u . PreMigrations , func ( i , j int ) bool {
2021-01-27 23:58:51 +00:00
return u . PreMigrations [ i ] . StartWithin > u . PreMigrations [ j ] . StartWithin //nolint:scopelint,gosec
2021-01-27 20:24:48 +00:00
} ) {
return xerrors . Errorf ( "pre-migrations must be sorted by start epoch" )
}
2020-10-03 00:09:56 +00:00
}
2021-01-26 23:00:55 +00:00
// Make sure the upgrade order makes sense.
2020-10-03 00:09:56 +00:00
for i := 1 ; i < len ( us ) ; i ++ {
prev := & us [ i - 1 ]
curr := & us [ i ]
if ! ( prev . Network <= curr . Network ) {
return xerrors . Errorf ( "cannot downgrade from version %d to version %d" , prev . Network , curr . Network )
}
// Make sure the heights make sense.
if prev . Height < 0 {
// Previous upgrade was disabled.
continue
}
if ! ( prev . Height < curr . Height ) {
return xerrors . Errorf ( "upgrade heights must be strictly increasing: upgrade %d was at height %d, followed by upgrade %d at height %d" , i - 1 , prev . Height , i , curr . Height )
}
}
return nil
2020-09-05 03:01:36 +00:00
}
2020-01-31 23:51:15 +00:00
2020-09-24 21:30:11 +00:00
func ( sm * StateManager ) handleStateForks ( ctx context . Context , root cid . Cid , height abi . ChainEpoch , cb ExecCallback , ts * types . TipSet ) ( cid . Cid , error ) {
retCid := root
var err error
2021-01-26 20:46:57 +00:00
u := sm . stateMigrations [ height ]
if u != nil && u . upgrade != nil {
2021-01-27 23:05:00 +00:00
startTime := time . Now ( )
2021-01-28 19:17:09 +00:00
log . Warnw ( "STARTING migration" , "height" , height , "from" , root )
2021-01-27 01:08:06 +00:00
// Yes, we clone the cache, even for the final upgrade epoch. Why? Reverts. We may
// have to migrate multiple times.
tmpCache := u . cache . Clone ( )
retCid , err = u . upgrade ( ctx , sm , tmpCache , cb , root , height , ts )
2020-07-28 12:31:13 +00:00
if err != nil {
2021-01-28 19:17:09 +00:00
log . Errorw ( "FAILED migration" , "height" , height , "from" , root , "error" , err )
2020-09-24 21:30:11 +00:00
return cid . Undef , err
2019-12-19 20:00:59 +00:00
}
2021-01-27 01:08:06 +00:00
// Yes, we update the cache, even for the final upgrade epoch. Why? Reverts. This
// can save us a _lot_ of time because very few actors will have changed if we
// do a small revert then need to re-run the migration.
u . cache . Update ( tmpCache )
2021-01-27 23:05:00 +00:00
log . Warnw ( "COMPLETED migration" ,
"height" , height ,
2021-01-28 19:17:09 +00:00
"from" , root ,
"to" , retCid ,
2021-01-27 23:05:00 +00:00
"duration" , time . Since ( startTime ) ,
)
2019-12-19 18:46:30 +00:00
}
2019-12-19 20:00:59 +00:00
2020-09-24 21:30:11 +00:00
return retCid , nil
2019-12-19 18:46:30 +00:00
}
2020-09-05 03:01:36 +00:00
2020-10-07 23:14:11 +00:00
func ( sm * StateManager ) hasExpensiveFork ( ctx context . Context , height abi . ChainEpoch ) bool {
_ , ok := sm . expensiveUpgrades [ height ]
2020-10-07 21:35:07 +00:00
return ok
}
2021-01-27 02:50:25 +00:00
func runPreMigration ( ctx context . Context , sm * StateManager , fn PreMigrationFunc , cache * nv10 . MemMigrationCache , ts * types . TipSet ) {
2021-01-27 23:05:00 +00:00
height := ts . Height ( )
parent := ts . ParentState ( )
startTime := time . Now ( )
log . Warn ( "STARTING pre-migration" )
2021-01-27 02:50:25 +00:00
// Clone the cache so we don't actually _update_ it
// till we're done. Otherwise, if we fail, the next
// migration to use the cache may assume that
// certain blocks exist, even if they don't.
tmpCache := cache . Clone ( )
2021-01-27 23:05:00 +00:00
err := fn ( ctx , sm , tmpCache , parent , height , ts )
2021-01-27 02:50:25 +00:00
if err != nil {
2021-01-27 23:05:00 +00:00
log . Errorw ( "FAILED pre-migration" , "error" , err )
2021-01-27 02:50:25 +00:00
return
}
// Finally, if everything worked, update the cache.
cache . Update ( tmpCache )
2021-01-27 23:05:00 +00:00
log . Warnw ( "COMPLETED pre-migration" , "duration" , time . Since ( startTime ) )
2021-01-27 02:50:25 +00:00
}
2021-01-26 20:46:57 +00:00
func ( sm * StateManager ) preMigrationWorker ( ctx context . Context ) {
2021-01-26 23:11:31 +00:00
defer close ( sm . shutdown )
2021-01-26 20:46:57 +00:00
ctx , cancel := context . WithCancel ( ctx )
defer cancel ( )
type op struct {
2021-01-26 22:57:38 +00:00
after abi . ChainEpoch
notAfter abi . ChainEpoch
2021-01-26 23:05:12 +00:00
run func ( ts * types . TipSet )
2021-01-26 20:46:57 +00:00
}
2021-01-26 23:11:31 +00:00
var wg sync . WaitGroup
defer wg . Wait ( )
2021-01-26 20:46:57 +00:00
// Turn each pre-migration into an operation in a schedule.
var schedule [ ] op
2021-01-26 22:57:38 +00:00
for upgradeEpoch , migration := range sm . stateMigrations {
2021-01-26 20:46:57 +00:00
cache := migration . cache
for _ , prem := range migration . preMigrations {
preCtx , preCancel := context . WithCancel ( ctx )
2021-01-26 23:15:14 +00:00
migrationFunc := prem . PreMigration
2021-01-26 20:46:57 +00:00
2021-01-27 23:58:51 +00:00
afterEpoch := upgradeEpoch - prem . StartWithin
notAfterEpoch := upgradeEpoch - prem . DontStartWithin
stopEpoch := upgradeEpoch - prem . StopWithin
// We can't start after we stop.
if notAfterEpoch > stopEpoch {
notAfterEpoch = stopEpoch - 1
}
2021-01-26 22:57:38 +00:00
2021-01-26 20:46:57 +00:00
// Add an op to start a pre-migration.
schedule = append ( schedule , op {
2021-01-26 22:57:38 +00:00
after : afterEpoch ,
notAfter : notAfterEpoch ,
2021-01-26 20:46:57 +00:00
// TODO: are these values correct?
2021-01-26 23:05:12 +00:00
run : func ( ts * types . TipSet ) {
2021-01-26 23:11:31 +00:00
wg . Add ( 1 )
2021-01-26 23:05:12 +00:00
go func ( ) {
2021-01-26 23:11:31 +00:00
defer wg . Done ( )
2021-01-27 02:50:25 +00:00
runPreMigration ( preCtx , sm , migrationFunc , cache , ts )
2021-01-26 23:05:12 +00:00
} ( )
2021-01-26 22:57:38 +00:00
} ,
2021-01-26 20:46:57 +00:00
} )
2021-01-26 22:57:38 +00:00
// Add an op to cancel the pre-migration if it's still running.
2021-01-26 20:46:57 +00:00
schedule = append ( schedule , op {
2021-01-27 23:58:51 +00:00
after : stopEpoch ,
2021-01-26 22:57:38 +00:00
notAfter : - 1 ,
2021-01-26 23:05:12 +00:00
run : func ( ts * types . TipSet ) { preCancel ( ) } ,
2021-01-26 20:46:57 +00:00
} )
}
}
// Then sort by epoch.
sort . Slice ( schedule , func ( i , j int ) bool {
2021-01-26 22:57:38 +00:00
return schedule [ i ] . after < schedule [ j ] . after
2021-01-26 20:46:57 +00:00
} )
// Finally, when the head changes, see if there's anything we need to do.
2021-01-27 23:58:51 +00:00
//
// We're intentionally ignoring reorgs as they don't matter for our purposes.
2021-01-26 20:46:57 +00:00
for change := range sm . cs . SubHeadChanges ( ctx ) {
for _ , head := range change {
for len ( schedule ) > 0 {
2021-01-26 22:57:38 +00:00
op := & schedule [ 0 ]
if head . Val . Height ( ) < op . after {
2021-01-26 20:46:57 +00:00
break
}
2021-01-26 22:57:38 +00:00
// If we haven't passed the pre-migration height...
2021-01-27 23:58:51 +00:00
if op . notAfter < 0 || head . Val . Height ( ) < op . notAfter {
2021-01-26 23:05:12 +00:00
op . run ( head . Val )
2021-01-26 22:57:38 +00:00
}
2021-01-26 20:46:57 +00:00
schedule = schedule [ 1 : ]
}
}
}
}
2020-10-13 05:20:49 +00:00
func doTransfer ( tree types . StateTree , from , to address . Address , amt abi . TokenAmount , cb func ( trace types . ExecutionTrace ) ) error {
2020-09-05 03:01:36 +00:00
fromAct , err := tree . GetActor ( from )
if err != nil {
return xerrors . Errorf ( "failed to get 'from' actor for transfer: %w" , err )
}
fromAct . Balance = types . BigSub ( fromAct . Balance , amt )
if fromAct . Balance . Sign ( ) < 0 {
return xerrors . Errorf ( "(sanity) deducted more funds from target account than it had (%s, %s)" , from , types . FIL ( amt ) )
}
if err := tree . SetActor ( from , fromAct ) ; err != nil {
return xerrors . Errorf ( "failed to persist from actor: %w" , err )
}
toAct , err := tree . GetActor ( to )
if err != nil {
return xerrors . Errorf ( "failed to get 'to' actor for transfer: %w" , err )
}
toAct . Balance = types . BigAdd ( toAct . Balance , amt )
if err := tree . SetActor ( to , toAct ) ; err != nil {
return xerrors . Errorf ( "failed to persist to actor: %w" , err )
}
2020-09-24 21:30:11 +00:00
if cb != nil {
// record the transfer in execution traces
2020-10-13 05:20:49 +00:00
cb ( types . ExecutionTrace {
2021-02-18 03:41:58 +00:00
Msg : makeFakeMsg ( from , to , amt , 0 ) ,
2021-02-19 07:03:00 +00:00
MsgRct : makeFakeRct ( ) ,
2020-10-13 05:20:49 +00:00
Error : "" ,
Duration : 0 ,
GasCharges : nil ,
Subcalls : nil ,
} )
2020-09-24 21:30:11 +00:00
}
2020-09-05 03:01:36 +00:00
return nil
}
2021-01-26 20:46:57 +00:00
func UpgradeFaucetBurnRecovery ( ctx context . Context , sm * StateManager , _ MigrationCache , cb ExecCallback , root cid . Cid , epoch abi . ChainEpoch , ts * types . TipSet ) ( cid . Cid , error ) {
2020-09-05 03:01:36 +00:00
// Some initial parameters
FundsForMiners := types . FromFil ( 1_000_000 )
LookbackEpoch := abi . ChainEpoch ( 32000 )
AccountCap := types . FromFil ( 0 )
BaseMinerBalance := types . FromFil ( 20 )
DesiredReimbursementBalance := types . FromFil ( 5_000_000 )
isSystemAccount := func ( addr address . Address ) ( bool , error ) {
id , err := address . IDFromAddress ( addr )
if err != nil {
return false , xerrors . Errorf ( "id address: %w" , err )
}
if id < 1000 {
return true , nil
}
return false , nil
}
minerFundsAlloc := func ( pow , tpow abi . StoragePower ) abi . TokenAmount {
return types . BigDiv ( types . BigMul ( pow , FundsForMiners ) , tpow )
}
// Grab lookback state for account checks
2020-09-08 20:45:44 +00:00
lbts , err := sm . ChainStore ( ) . GetTipsetByHeight ( ctx , LookbackEpoch , ts , false )
2020-09-05 03:01:36 +00:00
if err != nil {
2020-09-24 21:30:11 +00:00
return cid . Undef , xerrors . Errorf ( "failed to get tipset at lookback height: %w" , err )
2020-09-05 03:01:36 +00:00
}
2020-09-14 12:17:45 +00:00
lbtree , err := sm . ParentState ( lbts )
if err != nil {
2020-09-24 21:30:11 +00:00
return cid . Undef , xerrors . Errorf ( "loading state tree failed: %w" , err )
2020-09-05 03:01:36 +00:00
}
2020-09-24 21:30:11 +00:00
tree , err := sm . StateTree ( root )
if err != nil {
return cid . Undef , xerrors . Errorf ( "getting state tree: %w" , err )
2020-09-05 03:01:36 +00:00
}
type transfer struct {
From address . Address
To address . Address
Amt abi . TokenAmount
}
var transfers [ ] transfer
2020-10-13 05:20:49 +00:00
subcalls := make ( [ ] types . ExecutionTrace , 0 )
transferCb := func ( trace types . ExecutionTrace ) {
subcalls = append ( subcalls , trace )
}
2020-09-05 03:01:36 +00:00
// Take all excess funds away, put them into the reserve account
2020-09-24 21:30:11 +00:00
err = tree . ForEach ( func ( addr address . Address , act * types . Actor ) error {
2020-09-05 03:01:36 +00:00
switch act . Code {
2020-09-22 19:02:29 +00:00
case builtin0 . AccountActorCodeID , builtin0 . MultisigActorCodeID , builtin0 . PaymentChannelActorCodeID :
2020-09-05 03:01:36 +00:00
sysAcc , err := isSystemAccount ( addr )
if err != nil {
return xerrors . Errorf ( "checking system account: %w" , err )
}
if ! sysAcc {
transfers = append ( transfers , transfer {
From : addr ,
2020-10-11 22:17:28 +00:00
To : builtin . ReserveAddress ,
2020-09-05 03:01:36 +00:00
Amt : act . Balance ,
} )
}
2020-09-22 19:02:29 +00:00
case builtin0 . StorageMinerActorCodeID :
2020-09-18 21:59:27 +00:00
var st miner0 . State
2020-09-14 12:17:45 +00:00
if err := sm . ChainStore ( ) . Store ( ctx ) . Get ( ctx , act . Head , & st ) ; err != nil {
2020-09-05 03:01:36 +00:00
return xerrors . Errorf ( "failed to load miner state: %w" , err )
}
var available abi . TokenAmount
{
defer func ( ) {
if err := recover ( ) ; err != nil {
log . Warnf ( "Get available balance failed (%s, %s, %s): %s" , addr , act . Head , act . Balance , err )
}
available = abi . NewTokenAmount ( 0 )
} ( )
// this panics if the miner doesnt have enough funds to cover their locked pledge
available = st . GetAvailableBalance ( act . Balance )
}
2020-10-13 01:50:11 +00:00
if ! available . IsZero ( ) {
transfers = append ( transfers , transfer {
From : addr ,
To : builtin . ReserveAddress ,
Amt : available ,
} )
}
2020-09-05 03:01:36 +00:00
}
return nil
} )
if err != nil {
2020-09-24 21:30:11 +00:00
return cid . Undef , xerrors . Errorf ( "foreach over state tree failed: %w" , err )
2020-09-05 03:01:36 +00:00
}
// Execute transfers from previous step
for _ , t := range transfers {
2020-10-13 05:20:49 +00:00
if err := doTransfer ( tree , t . From , t . To , t . Amt , transferCb ) ; err != nil {
2020-09-24 21:30:11 +00:00
return cid . Undef , xerrors . Errorf ( "transfer %s %s->%s failed: %w" , t . Amt , t . From , t . To , err )
2020-09-05 03:01:36 +00:00
}
}
// pull up power table to give miners back some funds proportional to their power
2020-09-18 21:59:27 +00:00
var ps power0 . State
2020-09-22 19:02:29 +00:00
powAct , err := tree . GetActor ( builtin0 . StoragePowerActorAddr )
2020-09-05 03:01:36 +00:00
if err != nil {
2020-09-24 21:30:11 +00:00
return cid . Undef , xerrors . Errorf ( "failed to load power actor: %w" , err )
2020-09-05 03:01:36 +00:00
}
cst := cbor . NewCborStore ( sm . ChainStore ( ) . Blockstore ( ) )
if err := cst . Get ( ctx , powAct . Head , & ps ) ; err != nil {
2020-09-24 21:30:11 +00:00
return cid . Undef , xerrors . Errorf ( "failed to get power actor state: %w" , err )
2020-09-05 03:01:36 +00:00
}
totalPower := ps . TotalBytesCommitted
var transfersBack [ ] transfer
// Now, we return some funds to places where they are needed
2020-09-24 21:30:11 +00:00
err = tree . ForEach ( func ( addr address . Address , act * types . Actor ) error {
2020-09-05 03:01:36 +00:00
lbact , err := lbtree . GetActor ( addr )
if err != nil {
if ! xerrors . Is ( err , types . ErrActorNotFound ) {
return xerrors . Errorf ( "failed to get actor in lookback state" )
}
}
prevBalance := abi . NewTokenAmount ( 0 )
if lbact != nil {
prevBalance = lbact . Balance
}
switch act . Code {
2020-09-22 19:02:29 +00:00
case builtin0 . AccountActorCodeID , builtin0 . MultisigActorCodeID , builtin0 . PaymentChannelActorCodeID :
2020-09-05 03:01:36 +00:00
nbalance := big . Min ( prevBalance , AccountCap )
if nbalance . Sign ( ) != 0 {
transfersBack = append ( transfersBack , transfer {
2020-10-11 22:17:28 +00:00
From : builtin . ReserveAddress ,
2020-09-05 03:01:36 +00:00
To : addr ,
Amt : nbalance ,
} )
}
2020-09-22 19:02:29 +00:00
case builtin0 . StorageMinerActorCodeID :
2020-09-18 21:59:27 +00:00
var st miner0 . State
2020-09-14 12:17:45 +00:00
if err := sm . ChainStore ( ) . Store ( ctx ) . Get ( ctx , act . Head , & st ) ; err != nil {
2020-09-05 03:01:36 +00:00
return xerrors . Errorf ( "failed to load miner state: %w" , err )
}
2020-09-18 21:59:27 +00:00
var minfo miner0 . MinerInfo
2020-09-05 03:01:36 +00:00
if err := cst . Get ( ctx , st . Info , & minfo ) ; err != nil {
return xerrors . Errorf ( "failed to get miner info: %w" , err )
}
2020-09-22 18:14:55 +00:00
sectorsArr , err := adt0 . AsArray ( sm . ChainStore ( ) . Store ( ctx ) , st . Sectors )
2020-09-05 03:01:36 +00:00
if err != nil {
return xerrors . Errorf ( "failed to load sectors array: %w" , err )
}
slen := sectorsArr . Length ( )
power := types . BigMul ( types . NewInt ( slen ) , types . NewInt ( uint64 ( minfo . SectorSize ) ) )
mfunds := minerFundsAlloc ( power , totalPower )
transfersBack = append ( transfersBack , transfer {
2020-10-11 22:17:28 +00:00
From : builtin . ReserveAddress ,
2020-09-05 03:01:36 +00:00
To : minfo . Worker ,
Amt : mfunds ,
} )
// Now make sure to give each miner who had power at the lookback some FIL
lbact , err := lbtree . GetActor ( addr )
if err == nil {
2020-09-18 21:59:27 +00:00
var lbst miner0 . State
2020-09-14 12:17:45 +00:00
if err := sm . ChainStore ( ) . Store ( ctx ) . Get ( ctx , lbact . Head , & lbst ) ; err != nil {
2020-09-05 03:01:36 +00:00
return xerrors . Errorf ( "failed to load miner state: %w" , err )
}
2020-09-22 18:14:55 +00:00
lbsectors , err := adt0 . AsArray ( sm . ChainStore ( ) . Store ( ctx ) , lbst . Sectors )
2020-09-05 03:01:36 +00:00
if err != nil {
return xerrors . Errorf ( "failed to load lb sectors array: %w" , err )
}
if lbsectors . Length ( ) > 0 {
transfersBack = append ( transfersBack , transfer {
2020-10-11 22:17:28 +00:00
From : builtin . ReserveAddress ,
2020-09-05 03:01:36 +00:00
To : minfo . Worker ,
Amt : BaseMinerBalance ,
} )
}
} else {
log . Warnf ( "failed to get miner in lookback state: %s" , err )
}
}
return nil
} )
if err != nil {
2020-09-24 21:30:11 +00:00
return cid . Undef , xerrors . Errorf ( "foreach over state tree failed: %w" , err )
2020-09-05 03:01:36 +00:00
}
for _ , t := range transfersBack {
2020-10-13 05:20:49 +00:00
if err := doTransfer ( tree , t . From , t . To , t . Amt , transferCb ) ; err != nil {
2020-09-24 21:30:11 +00:00
return cid . Undef , xerrors . Errorf ( "transfer %s %s->%s failed: %w" , t . Amt , t . From , t . To , err )
2020-09-05 03:01:36 +00:00
}
}
// transfer all burnt funds back to the reserve account
2020-09-22 19:02:29 +00:00
burntAct , err := tree . GetActor ( builtin0 . BurntFundsActorAddr )
2020-09-05 03:01:36 +00:00
if err != nil {
2020-09-24 21:30:11 +00:00
return cid . Undef , xerrors . Errorf ( "failed to load burnt funds actor: %w" , err )
2020-09-05 03:01:36 +00:00
}
2020-10-13 05:20:49 +00:00
if err := doTransfer ( tree , builtin0 . BurntFundsActorAddr , builtin . ReserveAddress , burntAct . Balance , transferCb ) ; err != nil {
2020-09-24 21:30:11 +00:00
return cid . Undef , xerrors . Errorf ( "failed to unburn funds: %w" , err )
2020-09-05 03:01:36 +00:00
}
// Top up the reimbursement service
reimbAddr , err := address . NewFromString ( "t0111" )
if err != nil {
2020-09-24 21:30:11 +00:00
return cid . Undef , xerrors . Errorf ( "failed to parse reimbursement service address" )
2020-09-05 03:01:36 +00:00
}
reimb , err := tree . GetActor ( reimbAddr )
if err != nil {
2020-09-24 21:30:11 +00:00
return cid . Undef , xerrors . Errorf ( "failed to load reimbursement account actor: %w" , err )
2020-09-05 03:01:36 +00:00
}
difference := types . BigSub ( DesiredReimbursementBalance , reimb . Balance )
2020-10-13 05:20:49 +00:00
if err := doTransfer ( tree , builtin . ReserveAddress , reimbAddr , difference , transferCb ) ; err != nil {
2020-09-24 21:30:11 +00:00
return cid . Undef , xerrors . Errorf ( "failed to top up reimbursement account: %w" , err )
2020-09-05 03:01:36 +00:00
}
// Now, a final sanity check to make sure the balances all check out
total := abi . NewTokenAmount ( 0 )
2020-09-24 21:30:11 +00:00
err = tree . ForEach ( func ( addr address . Address , act * types . Actor ) error {
2020-09-05 03:01:36 +00:00
total = types . BigAdd ( total , act . Balance )
return nil
} )
if err != nil {
2020-09-24 21:30:11 +00:00
return cid . Undef , xerrors . Errorf ( "checking final state balance failed: %w" , err )
2020-09-05 03:01:36 +00:00
}
exp := types . FromFil ( build . FilBase )
if ! exp . Equals ( total ) {
2020-09-24 21:30:11 +00:00
return cid . Undef , xerrors . Errorf ( "resultant state tree account balance was not correct: %s" , total )
}
2020-10-13 05:20:49 +00:00
if cb != nil {
// record the transfer in execution traces
2021-02-18 03:41:58 +00:00
fakeMsg := makeFakeMsg ( builtin . SystemActorAddr , builtin . SystemActorAddr , big . Zero ( ) , uint64 ( epoch ) )
2020-10-13 05:20:49 +00:00
if err := cb ( fakeMsg . Cid ( ) , fakeMsg , & vm . ApplyRet {
2021-02-19 07:03:00 +00:00
MessageReceipt : * makeFakeRct ( ) ,
2020-10-13 05:20:49 +00:00
ActorErr : nil ,
ExecutionTrace : types . ExecutionTrace {
Msg : fakeMsg ,
2021-02-19 07:03:00 +00:00
MsgRct : makeFakeRct ( ) ,
2020-10-13 05:20:49 +00:00
Error : "" ,
Duration : 0 ,
GasCharges : nil ,
Subcalls : subcalls ,
} ,
Duration : 0 ,
2020-10-16 01:12:38 +00:00
GasCosts : nil ,
2020-10-13 05:20:49 +00:00
} ) ; err != nil {
return cid . Undef , xerrors . Errorf ( "recording transfers: %w" , err )
}
}
2020-09-24 21:30:11 +00:00
return tree . Flush ( ctx )
}
2021-01-26 20:46:57 +00:00
func UpgradeIgnition ( ctx context . Context , sm * StateManager , _ MigrationCache , cb ExecCallback , root cid . Cid , epoch abi . ChainEpoch , ts * types . TipSet ) ( cid . Cid , error ) {
2020-09-24 21:30:11 +00:00
store := sm . cs . Store ( ctx )
2020-10-05 17:35:21 +00:00
if build . UpgradeLiftoffHeight <= epoch {
return cid . Undef , xerrors . Errorf ( "liftoff height must be beyond ignition height" )
}
2020-10-02 03:37:14 +00:00
nst , err := nv3 . MigrateStateTree ( ctx , store , root , epoch )
2020-09-24 21:30:11 +00:00
if err != nil {
return cid . Undef , xerrors . Errorf ( "migrating actors state: %w" , err )
}
tree , err := sm . StateTree ( nst )
if err != nil {
return cid . Undef , xerrors . Errorf ( "getting state tree: %w" , err )
}
err = setNetworkName ( ctx , store , tree , "ignition" )
if err != nil {
return cid . Undef , xerrors . Errorf ( "setting network name: %w" , err )
}
split1 , err := address . NewFromString ( "t0115" )
if err != nil {
return cid . Undef , xerrors . Errorf ( "first split address: %w" , err )
}
split2 , err := address . NewFromString ( "t0116" )
if err != nil {
return cid . Undef , xerrors . Errorf ( "second split address: %w" , err )
}
2020-10-08 01:09:33 +00:00
err = resetGenesisMsigs0 ( ctx , sm , store , tree , build . UpgradeLiftoffHeight )
2020-09-24 21:30:11 +00:00
if err != nil {
return cid . Undef , xerrors . Errorf ( "resetting genesis msig start epochs: %w" , err )
}
2020-10-08 01:09:33 +00:00
err = splitGenesisMultisig0 ( ctx , cb , split1 , store , tree , 50 , epoch )
2020-09-24 21:30:11 +00:00
if err != nil {
return cid . Undef , xerrors . Errorf ( "splitting first msig: %w" , err )
}
2020-10-08 01:09:33 +00:00
err = splitGenesisMultisig0 ( ctx , cb , split2 , store , tree , 50 , epoch )
2020-09-24 21:30:11 +00:00
if err != nil {
return cid . Undef , xerrors . Errorf ( "splitting second msig: %w" , err )
}
2020-10-02 03:37:14 +00:00
err = nv3 . CheckStateTree ( ctx , store , nst , epoch , builtin0 . TotalFilecoin )
2020-09-24 21:30:11 +00:00
if err != nil {
return cid . Undef , xerrors . Errorf ( "sanity check after ignition upgrade failed: %w" , err )
}
return tree . Flush ( ctx )
}
2021-01-26 20:46:57 +00:00
func UpgradeRefuel ( ctx context . Context , sm * StateManager , _ MigrationCache , cb ExecCallback , root cid . Cid , epoch abi . ChainEpoch , ts * types . TipSet ) ( cid . Cid , error ) {
2020-10-07 23:54:03 +00:00
2020-10-06 21:47:03 +00:00
store := sm . cs . Store ( ctx )
tree , err := sm . StateTree ( root )
if err != nil {
return cid . Undef , xerrors . Errorf ( "getting state tree: %w" , err )
}
2020-10-08 01:09:33 +00:00
err = resetMultisigVesting0 ( ctx , store , tree , builtin . SaftAddress , 0 , 0 , big . Zero ( ) )
2020-10-06 21:47:03 +00:00
if err != nil {
return cid . Undef , xerrors . Errorf ( "tweaking msig vesting: %w" , err )
}
2020-10-08 01:09:33 +00:00
err = resetMultisigVesting0 ( ctx , store , tree , builtin . ReserveAddress , 0 , 0 , big . Zero ( ) )
2020-10-06 21:47:03 +00:00
if err != nil {
return cid . Undef , xerrors . Errorf ( "tweaking msig vesting: %w" , err )
}
2020-10-08 01:09:33 +00:00
err = resetMultisigVesting0 ( ctx , store , tree , builtin . RootVerifierAddress , 0 , 0 , big . Zero ( ) )
2020-10-06 21:47:03 +00:00
if err != nil {
return cid . Undef , xerrors . Errorf ( "tweaking msig vesting: %w" , err )
}
return tree . Flush ( ctx )
}
2021-01-26 20:46:57 +00:00
func UpgradeActorsV2 ( ctx context . Context , sm * StateManager , _ MigrationCache , cb ExecCallback , root cid . Cid , epoch abi . ChainEpoch , ts * types . TipSet ) ( cid . Cid , error ) {
2020-10-06 23:15:19 +00:00
buf := bufbstore . NewTieredBstore ( sm . cs . Blockstore ( ) , bstore . NewTemporarySync ( ) )
store := store . ActorStore ( ctx , buf )
2020-09-28 22:50:54 +00:00
2020-10-06 22:22:54 +00:00
info , err := store . Put ( ctx , new ( types . StateInfo0 ) )
2020-09-28 22:50:54 +00:00
if err != nil {
return cid . Undef , xerrors . Errorf ( "failed to create new state info for actors v2: %w" , err )
}
2020-11-08 04:05:52 +00:00
newHamtRoot , err := nv4 . MigrateStateTree ( ctx , store , root , epoch , nv4 . DefaultConfig ( ) )
2020-09-28 22:50:54 +00:00
if err != nil {
return cid . Undef , xerrors . Errorf ( "upgrading to actors v2: %w" , err )
}
newRoot , err := store . Put ( ctx , & types . StateRoot {
2020-10-07 00:51:43 +00:00
Version : types . StateTreeVersion1 ,
2020-09-28 22:50:54 +00:00
Actors : newHamtRoot ,
Info : info ,
} )
if err != nil {
return cid . Undef , xerrors . Errorf ( "failed to persist new state root: %w" , err )
}
2020-09-29 00:42:29 +00:00
// perform some basic sanity checks to make sure everything still works.
2020-09-28 22:50:54 +00:00
if newSm , err := state . LoadStateTree ( store , newRoot ) ; err != nil {
return cid . Undef , xerrors . Errorf ( "state tree sanity load failed: %w" , err )
} else if newRoot2 , err := newSm . Flush ( ctx ) ; err != nil {
return cid . Undef , xerrors . Errorf ( "state tree sanity flush failed: %w" , err )
} else if newRoot2 != newRoot {
return cid . Undef , xerrors . Errorf ( "state-root mismatch: %s != %s" , newRoot , newRoot2 )
} else if _ , err := newSm . GetActor ( builtin0 . InitActorAddr ) ; err != nil {
return cid . Undef , xerrors . Errorf ( "failed to load init actor after upgrade: %w" , err )
}
2020-10-06 23:15:19 +00:00
{
from := buf
to := buf . Read ( )
if err := vm . Copy ( ctx , from , to , newRoot ) ; err != nil {
2020-10-07 12:10:23 +00:00
return cid . Undef , xerrors . Errorf ( "copying migrated tree: %w" , err )
2020-10-06 23:15:19 +00:00
}
}
2020-09-28 22:50:54 +00:00
return newRoot , nil
}
2021-01-26 20:46:57 +00:00
func UpgradeLiftoff ( ctx context . Context , sm * StateManager , _ MigrationCache , cb ExecCallback , root cid . Cid , epoch abi . ChainEpoch , ts * types . TipSet ) ( cid . Cid , error ) {
2020-09-24 21:30:11 +00:00
tree , err := sm . StateTree ( root )
if err != nil {
return cid . Undef , xerrors . Errorf ( "getting state tree: %w" , err )
}
err = setNetworkName ( ctx , sm . cs . Store ( ctx ) , tree , "mainnet" )
if err != nil {
return cid . Undef , xerrors . Errorf ( "setting network name: %w" , err )
}
return tree . Flush ( ctx )
}
2021-01-26 20:46:57 +00:00
func UpgradeCalico ( ctx context . Context , sm * StateManager , _ MigrationCache , cb ExecCallback , root cid . Cid , epoch abi . ChainEpoch , ts * types . TipSet ) ( cid . Cid , error ) {
2020-11-08 04:05:52 +00:00
store := sm . cs . Store ( ctx )
2020-11-06 17:56:10 +00:00
var stateRoot types . StateRoot
if err := store . Get ( ctx , root , & stateRoot ) ; err != nil {
return cid . Undef , xerrors . Errorf ( "failed to decode state root: %w" , err )
2020-11-08 04:05:52 +00:00
}
2020-11-06 17:56:10 +00:00
if stateRoot . Version != types . StateTreeVersion1 {
return cid . Undef , xerrors . Errorf (
"expected state root version 1 for calico upgrade, got %d" ,
stateRoot . Version ,
)
}
newHamtRoot , err := nv7 . MigrateStateTree ( ctx , store , stateRoot . Actors , epoch , nv7 . DefaultConfig ( ) )
2020-11-08 04:05:52 +00:00
if err != nil {
return cid . Undef , xerrors . Errorf ( "running nv7 migration: %w" , err )
}
newRoot , err := store . Put ( ctx , & types . StateRoot {
2020-11-06 17:56:10 +00:00
Version : stateRoot . Version ,
2020-11-08 04:05:52 +00:00
Actors : newHamtRoot ,
2020-11-06 17:56:10 +00:00
Info : stateRoot . Info ,
2020-11-08 04:05:52 +00:00
} )
if err != nil {
return cid . Undef , xerrors . Errorf ( "failed to persist new state root: %w" , err )
}
// perform some basic sanity checks to make sure everything still works.
if newSm , err := state . LoadStateTree ( store , newRoot ) ; err != nil {
return cid . Undef , xerrors . Errorf ( "state tree sanity load failed: %w" , err )
} else if newRoot2 , err := newSm . Flush ( ctx ) ; err != nil {
return cid . Undef , xerrors . Errorf ( "state tree sanity flush failed: %w" , err )
} else if newRoot2 != newRoot {
return cid . Undef , xerrors . Errorf ( "state-root mismatch: %s != %s" , newRoot , newRoot2 )
} else if _ , err := newSm . GetActor ( builtin0 . InitActorAddr ) ; err != nil {
return cid . Undef , xerrors . Errorf ( "failed to load init actor after upgrade: %w" , err )
}
return newRoot , nil
}
2021-02-18 22:16:32 +00:00
func terminateActor ( ctx context . Context , tree * state . StateTree , addr address . Address , cb ExecCallback , epoch abi . ChainEpoch ) error {
2021-02-18 03:41:58 +00:00
a , err := tree . GetActor ( addr )
if xerrors . Is ( err , types . ErrActorNotFound ) {
return types . ErrActorNotFound
2021-02-19 07:03:00 +00:00
} else if err != nil {
return xerrors . Errorf ( "failed to get actor to delete: %w" , err )
2021-02-18 03:41:58 +00:00
}
var trace types . ExecutionTrace
if err := doTransfer ( tree , addr , builtin . BurntFundsActorAddr , a . Balance , func ( t types . ExecutionTrace ) {
trace = t
} ) ; err != nil {
return xerrors . Errorf ( "transferring terminated actor's balance: %w" , err )
}
if cb != nil {
// record the transfer in execution traces
fakeMsg := makeFakeMsg ( builtin . SystemActorAddr , addr , big . Zero ( ) , uint64 ( epoch ) )
if err := cb ( fakeMsg . Cid ( ) , fakeMsg , & vm . ApplyRet {
2021-02-19 07:03:00 +00:00
MessageReceipt : * makeFakeRct ( ) ,
2021-02-18 03:41:58 +00:00
ActorErr : nil ,
ExecutionTrace : trace ,
Duration : 0 ,
GasCosts : nil ,
} ) ; err != nil {
return xerrors . Errorf ( "recording transfers: %w" , err )
}
}
2021-02-18 22:16:32 +00:00
err = tree . DeleteActor ( addr )
if err != nil {
return xerrors . Errorf ( "deleting actor from tree: %w" , err )
}
ia , err := tree . GetActor ( init_ . Address )
if err != nil {
return xerrors . Errorf ( "loading init actor: %w" , err )
}
2021-02-19 07:03:00 +00:00
ias , err := init_ . Load ( & state . AdtStore { IpldStore : tree . Store } , ia )
2021-02-18 22:16:32 +00:00
if err != nil {
return xerrors . Errorf ( "loading init actor state: %w" , err )
}
2021-02-19 07:03:00 +00:00
if err := ias . Remove ( addr ) ; err != nil {
2021-02-18 22:16:32 +00:00
return xerrors . Errorf ( "deleting entry from address map: %w" , err )
}
2021-02-19 07:03:00 +00:00
nih , err := tree . Store . Put ( ctx , ias )
2021-02-18 22:16:32 +00:00
if err != nil {
return xerrors . Errorf ( "writing new init actor state: %w" , err )
}
ia . Head = nih
return tree . SetActor ( init_ . Address , ia )
2021-02-18 03:41:58 +00:00
}
2021-01-26 22:57:38 +00:00
func UpgradeActorsV3 ( ctx context . Context , sm * StateManager , cache MigrationCache , cb ExecCallback , root cid . Cid , epoch abi . ChainEpoch , ts * types . TipSet ) ( cid . Cid , error ) {
2021-01-27 23:47:34 +00:00
// Use all the CPUs except 3.
workerCount := runtime . NumCPU ( ) - 3
if workerCount <= 0 {
workerCount = 1
}
2021-01-28 19:17:28 +00:00
config := nv10 . Config {
MaxWorkers : uint ( workerCount ) ,
JobQueueSize : 1000 ,
ResultQueueSize : 100 ,
ProgressLogPeriod : 10 * time . Second ,
}
2021-01-26 22:57:38 +00:00
newRoot , err := upgradeActorsV3Common ( ctx , sm , cache , root , epoch , ts , config )
if err != nil {
2021-01-26 23:21:55 +00:00
return cid . Undef , xerrors . Errorf ( "migrating actors v3 state: %w" , err )
2021-01-26 22:57:38 +00:00
}
2021-02-18 03:41:58 +00:00
tree , err := sm . StateTree ( newRoot )
if err != nil {
return cid . Undef , xerrors . Errorf ( "getting state tree: %w" , err )
}
2021-02-18 20:43:20 +00:00
if build . BuildType == build . BuildMainnet {
2021-02-18 22:16:32 +00:00
err := terminateActor ( ctx , tree , build . ZeroAddress , cb , epoch )
2021-02-18 20:43:20 +00:00
if err != nil && ! xerrors . Is ( err , types . ErrActorNotFound ) {
return cid . Undef , xerrors . Errorf ( "deleting zero bls actor: %w" , err )
}
2021-02-18 03:41:58 +00:00
2021-02-18 20:43:20 +00:00
newRoot , err = tree . Flush ( ctx )
if err != nil {
return cid . Undef , xerrors . Errorf ( "flushing state tree: %w" , err )
}
2021-02-18 03:41:58 +00:00
}
2021-01-26 22:57:38 +00:00
return newRoot , nil
}
func PreUpgradeActorsV3 ( ctx context . Context , sm * StateManager , cache MigrationCache , root cid . Cid , epoch abi . ChainEpoch , ts * types . TipSet ) error {
2021-01-27 23:47:34 +00:00
// Use half the CPUs for pre-migration, but leave at least 3.
workerCount := runtime . NumCPU ( )
if workerCount <= 4 {
workerCount = 1
} else {
workerCount /= 2
}
config := nv10 . Config { MaxWorkers : uint ( workerCount ) }
2021-01-26 22:57:38 +00:00
_ , err := upgradeActorsV3Common ( ctx , sm , cache , root , epoch , ts , config )
return err
}
func upgradeActorsV3Common (
ctx context . Context , sm * StateManager , cache MigrationCache ,
root cid . Cid , epoch abi . ChainEpoch , ts * types . TipSet ,
config nv10 . Config ,
) ( cid . Cid , error ) {
2021-01-19 03:42:23 +00:00
buf := bufbstore . NewTieredBstore ( sm . cs . Blockstore ( ) , bstore . NewTemporarySync ( ) )
store := store . ActorStore ( ctx , buf )
// Load the state root.
var stateRoot types . StateRoot
if err := store . Get ( ctx , root , & stateRoot ) ; err != nil {
return cid . Undef , xerrors . Errorf ( "failed to decode state root: %w" , err )
}
if stateRoot . Version != types . StateTreeVersion1 {
return cid . Undef , xerrors . Errorf (
"expected state root version 1 for actors v3 upgrade, got %d" ,
stateRoot . Version ,
)
}
// Perform the migration
2021-01-19 16:48:10 +00:00
newHamtRoot , err := nv10 . MigrateStateTree ( ctx , store , stateRoot . Actors , epoch , config , migrationLogger { } , cache )
2021-01-19 03:42:23 +00:00
if err != nil {
return cid . Undef , xerrors . Errorf ( "upgrading to actors v2: %w" , err )
}
// Persist the result.
newRoot , err := store . Put ( ctx , & types . StateRoot {
Version : types . StateTreeVersion2 ,
Actors : newHamtRoot ,
Info : stateRoot . Info ,
} )
if err != nil {
return cid . Undef , xerrors . Errorf ( "failed to persist new state root: %w" , err )
}
// Persist the new tree.
{
from := buf
to := buf . Read ( )
if err := vm . Copy ( ctx , from , to , newRoot ) ; err != nil {
return cid . Undef , xerrors . Errorf ( "copying migrated tree: %w" , err )
}
}
return newRoot , nil
}
2020-09-28 22:54:48 +00:00
func setNetworkName ( ctx context . Context , store adt . Store , tree * state . StateTree , name string ) error {
2020-09-24 21:30:11 +00:00
ia , err := tree . GetActor ( builtin0 . InitActorAddr )
if err != nil {
return xerrors . Errorf ( "getting init actor: %w" , err )
}
2020-09-28 22:54:48 +00:00
initState , err := init_ . Load ( store , ia )
if err != nil {
2020-09-24 21:30:11 +00:00
return xerrors . Errorf ( "reading init state: %w" , err )
}
2020-09-28 22:59:11 +00:00
if err := initState . SetNetworkName ( name ) ; err != nil {
return xerrors . Errorf ( "setting network name: %w" , err )
}
2020-09-24 21:30:11 +00:00
2020-09-28 22:54:48 +00:00
ia . Head , err = store . Put ( ctx , initState )
2020-09-24 21:30:11 +00:00
if err != nil {
return xerrors . Errorf ( "writing new init state: %w" , err )
}
if err := tree . SetActor ( builtin0 . InitActorAddr , ia ) ; err != nil {
return xerrors . Errorf ( "setting init actor: %w" , err )
}
return nil
}
2020-10-08 01:09:33 +00:00
func splitGenesisMultisig0 ( ctx context . Context , cb ExecCallback , addr address . Address , store adt0 . Store , tree * state . StateTree , portions uint64 , epoch abi . ChainEpoch ) error {
2020-09-24 21:30:11 +00:00
if portions < 1 {
return xerrors . Errorf ( "cannot split into 0 portions" )
}
mact , err := tree . GetActor ( addr )
if err != nil {
return xerrors . Errorf ( "getting msig actor: %w" , err )
}
mst , err := multisig . Load ( store , mact )
if err != nil {
return xerrors . Errorf ( "getting msig state: %w" , err )
}
signers , err := mst . Signers ( )
if err != nil {
return xerrors . Errorf ( "getting msig signers: %w" , err )
}
thresh , err := mst . Threshold ( )
if err != nil {
return xerrors . Errorf ( "getting msig threshold: %w" , err )
}
ibal , err := mst . InitialBalance ( )
if err != nil {
return xerrors . Errorf ( "getting msig initial balance: %w" , err )
}
se , err := mst . StartEpoch ( )
if err != nil {
return xerrors . Errorf ( "getting msig start epoch: %w" , err )
}
ud , err := mst . UnlockDuration ( )
if err != nil {
return xerrors . Errorf ( "getting msig unlock duration: %w" , err )
}
pending , err := adt0 . MakeEmptyMap ( store ) . Root ( )
if err != nil {
return xerrors . Errorf ( "failed to create empty map: %w" , err )
}
newIbal := big . Div ( ibal , types . NewInt ( portions ) )
newState := & multisig0 . State {
Signers : signers ,
NumApprovalsThreshold : thresh ,
NextTxnID : 0 ,
InitialBalance : newIbal ,
StartEpoch : se ,
UnlockDuration : ud ,
PendingTxns : pending ,
}
scid , err := store . Put ( ctx , newState )
if err != nil {
return xerrors . Errorf ( "storing new state: %w" , err )
}
newActor := types . Actor {
Code : builtin0 . MultisigActorCodeID ,
Head : scid ,
Nonce : 0 ,
Balance : big . Zero ( ) ,
}
i := uint64 ( 0 )
2020-10-13 05:20:49 +00:00
subcalls := make ( [ ] types . ExecutionTrace , 0 , portions )
transferCb := func ( trace types . ExecutionTrace ) {
subcalls = append ( subcalls , trace )
}
2020-09-24 21:30:11 +00:00
for i < portions {
keyAddr , err := makeKeyAddr ( addr , i )
if err != nil {
return xerrors . Errorf ( "creating key address: %w" , err )
}
idAddr , err := tree . RegisterNewAddress ( keyAddr )
if err != nil {
return xerrors . Errorf ( "registering new address: %w" , err )
}
err = tree . SetActor ( idAddr , & newActor )
if err != nil {
return xerrors . Errorf ( "setting new msig actor state: %w" , err )
}
2020-10-13 05:20:49 +00:00
if err := doTransfer ( tree , addr , idAddr , newIbal , transferCb ) ; err != nil {
2020-09-24 21:30:11 +00:00
return xerrors . Errorf ( "transferring split msig balance: %w" , err )
}
i ++
}
2020-10-13 05:20:49 +00:00
if cb != nil {
// record the transfer in execution traces
2021-02-18 03:41:58 +00:00
fakeMsg := makeFakeMsg ( builtin . SystemActorAddr , addr , big . Zero ( ) , uint64 ( epoch ) )
2020-10-13 05:20:49 +00:00
if err := cb ( fakeMsg . Cid ( ) , fakeMsg , & vm . ApplyRet {
2021-02-19 07:03:00 +00:00
MessageReceipt : * makeFakeRct ( ) ,
2020-10-13 05:20:49 +00:00
ActorErr : nil ,
ExecutionTrace : types . ExecutionTrace {
Msg : fakeMsg ,
2021-02-19 07:03:00 +00:00
MsgRct : makeFakeRct ( ) ,
2020-10-13 05:20:49 +00:00
Error : "" ,
Duration : 0 ,
GasCharges : nil ,
Subcalls : subcalls ,
} ,
Duration : 0 ,
2020-10-16 01:12:38 +00:00
GasCosts : nil ,
2020-10-13 05:20:49 +00:00
} ) ; err != nil {
return xerrors . Errorf ( "recording transfers: %w" , err )
}
}
2020-09-24 21:30:11 +00:00
return nil
}
func makeKeyAddr ( splitAddr address . Address , count uint64 ) ( address . Address , error ) {
var b bytes . Buffer
if err := splitAddr . MarshalCBOR ( & b ) ; err != nil {
return address . Undef , xerrors . Errorf ( "marshalling split address: %w" , err )
}
if err := binary . Write ( & b , binary . BigEndian , count ) ; err != nil {
return address . Undef , xerrors . Errorf ( "writing count into a buffer: %w" , err )
}
if err := binary . Write ( & b , binary . BigEndian , [ ] byte ( "Ignition upgrade" ) ) ; err != nil {
return address . Undef , xerrors . Errorf ( "writing fork name into a buffer: %w" , err )
}
addr , err := address . NewActorAddress ( b . Bytes ( ) )
if err != nil {
return address . Undef , xerrors . Errorf ( "create actor address: %w" , err )
}
return addr , nil
}
2020-10-06 21:47:03 +00:00
// TODO: After the Liftoff epoch, refactor this to use resetMultisigVesting
2020-10-08 01:09:33 +00:00
func resetGenesisMsigs0 ( ctx context . Context , sm * StateManager , store adt0 . Store , tree * state . StateTree , startEpoch abi . ChainEpoch ) error {
2020-09-24 21:30:11 +00:00
gb , err := sm . cs . GetGenesis ( )
if err != nil {
return xerrors . Errorf ( "getting genesis block: %w" , err )
}
gts , err := types . NewTipSet ( [ ] * types . BlockHeader { gb } )
if err != nil {
return xerrors . Errorf ( "getting genesis tipset: %w" , err )
}
cst := cbor . NewCborStore ( sm . cs . Blockstore ( ) )
genesisTree , err := state . LoadStateTree ( cst , gts . ParentState ( ) )
if err != nil {
return xerrors . Errorf ( "loading state tree: %w" , err )
}
err = genesisTree . ForEach ( func ( addr address . Address , genesisActor * types . Actor ) error {
if genesisActor . Code == builtin0 . MultisigActorCodeID {
currActor , err := tree . GetActor ( addr )
if err != nil {
return xerrors . Errorf ( "loading actor: %w" , err )
}
var currState multisig0 . State
if err := store . Get ( ctx , currActor . Head , & currState ) ; err != nil {
return xerrors . Errorf ( "reading multisig state: %w" , err )
}
2020-10-05 17:35:21 +00:00
currState . StartEpoch = startEpoch
2020-09-24 21:30:11 +00:00
currActor . Head , err = store . Put ( ctx , & currState )
if err != nil {
return xerrors . Errorf ( "writing new multisig state: %w" , err )
}
if err := tree . SetActor ( addr , currActor ) ; err != nil {
return xerrors . Errorf ( "setting multisig actor: %w" , err )
}
}
return nil
} )
if err != nil {
return xerrors . Errorf ( "iterating over genesis actors: %w" , err )
2020-09-05 03:01:36 +00:00
}
return nil
}
2020-10-06 21:47:03 +00:00
2020-10-08 01:09:33 +00:00
func resetMultisigVesting0 ( ctx context . Context , store adt0 . Store , tree * state . StateTree , addr address . Address , startEpoch abi . ChainEpoch , duration abi . ChainEpoch , balance abi . TokenAmount ) error {
2020-10-06 21:47:03 +00:00
act , err := tree . GetActor ( addr )
if err != nil {
return xerrors . Errorf ( "getting actor: %w" , err )
}
if ! builtin . IsMultisigActor ( act . Code ) {
return xerrors . Errorf ( "actor wasn't msig: %w" , err )
}
var msigState multisig0 . State
if err := store . Get ( ctx , act . Head , & msigState ) ; err != nil {
return xerrors . Errorf ( "reading multisig state: %w" , err )
}
msigState . StartEpoch = startEpoch
msigState . UnlockDuration = duration
msigState . InitialBalance = balance
act . Head , err = store . Put ( ctx , & msigState )
if err != nil {
return xerrors . Errorf ( "writing new multisig state: %w" , err )
}
if err := tree . SetActor ( addr , act ) ; err != nil {
return xerrors . Errorf ( "setting multisig actor: %w" , err )
}
return nil
}
2021-02-18 03:41:58 +00:00
func makeFakeMsg ( from address . Address , to address . Address , amt abi . TokenAmount , nonce uint64 ) * types . Message {
return & types . Message {
From : from ,
To : to ,
Value : amt ,
Nonce : nonce ,
}
}
2021-02-19 07:03:00 +00:00
func makeFakeRct ( ) * types . MessageReceipt {
return & types . MessageReceipt {
ExitCode : 0 ,
Return : nil ,
GasUsed : 0 ,
}
}