/
top.go
84 lines (71 loc) · 2.62 KB
/
top.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package nv3
import (
"context"
address "github.com/chenjianmei111/go-address"
"github.com/chenjianmei111/go-state-types/abi"
"github.com/chenjianmei111/go-state-types/big"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
"golang.org/x/xerrors"
"github.com/chenjianmei111/specs-actors/actors/builtin"
"github.com/chenjianmei111/specs-actors/actors/states"
"github.com/chenjianmei111/specs-actors/actors/util/adt"
)
//
// State migration for network version 3.
// This is an in-place upgrade that makes functionality changes guarded by checks on the network version,
// and migrates some state.
//
// Loads and migrates the Filecoin state tree from a root, writing the new state tree blocks into the
// same store.
// Returns the new root of the state tree.
func MigrateStateTree(ctx context.Context, store cbor.IpldStore, root cid.Cid, priorEpoch abi.ChainEpoch) (cid.Cid, error) {
// Set up store and state tree.
adtStore := adt.WrapStore(ctx, store)
tree, err := states.LoadTree(adtStore, root)
if err != nil {
return cid.Undef, err
}
// Iterate all actors in old state root, set new actor states as we go.
if err = tree.ForEach(func(addr address.Address, actorIn *states.Actor) error {
migration, found := migrators[actorIn.Code]
if !found {
return nil // No migration for this actor type
}
headOut, err := migration.MigrateState(ctx, store, actorIn.Head, priorEpoch, addr, tree)
if err != nil {
return xerrors.Errorf("state migration error on %s actor at addr %s: %w", builtin.ActorNameByCode(actorIn.Code), addr, err)
}
// Write new state root with the migrated state.
actorOut := states.Actor{
Code: actorIn.Code,
Head: headOut,
CallSeqNum: actorIn.CallSeqNum,
Balance: actorIn.Balance,
}
return tree.SetActor(addr, &actorOut)
}); err != nil {
return cid.Undef, err
}
return tree.Flush()
}
// Checks that a state tree is internally consistent.
// This performs only very basic checks. Versions in v2 will be much more thorough.
func CheckStateTree(ctx context.Context, store cbor.IpldStore, root cid.Cid, priorEpoch abi.ChainEpoch, expectedBalanceTotal abi.TokenAmount) error {
adtStore := adt.WrapStore(ctx, store)
tree, err := states.LoadTree(adtStore, root)
if err != nil {
return err
}
balanceTotal := big.Zero()
if err = tree.ForEach(func(addr address.Address, actor *states.Actor) error {
balanceTotal = big.Add(balanceTotal, actor.Balance)
return nil
}); err != nil {
return err
}
if !balanceTotal.Equals(expectedBalanceTotal) {
return xerrors.Errorf("balance total %v doesn't match expected %v", balanceTotal, expectedBalanceTotal)
}
return nil
}