2020-08-21 01:10:11 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
2020-08-22 03:58:39 +00:00
|
|
|
"sort"
|
2020-08-21 01:10:11 +00:00
|
|
|
|
2020-09-29 04:24:38 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
|
|
|
|
2020-08-22 03:58:39 +00:00
|
|
|
"github.com/fatih/color"
|
2020-08-21 01:10:11 +00:00
|
|
|
"github.com/ipfs/go-datastore"
|
2020-08-22 03:58:39 +00:00
|
|
|
cbor "github.com/ipfs/go-ipld-cbor"
|
2020-08-21 01:10:11 +00:00
|
|
|
"github.com/urfave/cli/v2"
|
|
|
|
"golang.org/x/xerrors"
|
|
|
|
|
2020-08-22 03:58:39 +00:00
|
|
|
"github.com/filecoin-project/go-address"
|
2020-09-07 03:49:10 +00:00
|
|
|
"github.com/filecoin-project/go-state-types/big"
|
2020-09-21 22:18:30 +00:00
|
|
|
|
2020-08-22 03:58:39 +00:00
|
|
|
"github.com/filecoin-project/lotus/build"
|
2020-09-21 22:18:30 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/actors/adt"
|
|
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/account"
|
|
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
|
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
|
2020-08-22 03:58:39 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/state"
|
2020-08-21 01:10:11 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
|
|
|
"github.com/filecoin-project/lotus/chain/store"
|
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
|
|
|
"github.com/filecoin-project/lotus/lib/blockstore"
|
|
|
|
)
|
|
|
|
|
2020-08-22 03:58:39 +00:00
|
|
|
type addrInfo struct {
|
|
|
|
Key address.Address
|
|
|
|
Balance types.FIL
|
|
|
|
}
|
|
|
|
|
|
|
|
type msigInfo struct {
|
|
|
|
Signers []address.Address
|
|
|
|
Balance types.FIL
|
|
|
|
Threshold uint64
|
|
|
|
}
|
|
|
|
|
|
|
|
type minerInfo struct {
|
|
|
|
}
|
|
|
|
|
2020-08-21 01:10:11 +00:00
|
|
|
var genesisVerifyCmd = &cli.Command{
|
|
|
|
Name: "verify-genesis",
|
|
|
|
Description: "verify some basic attributes of a genesis car file",
|
|
|
|
Action: func(cctx *cli.Context) error {
|
|
|
|
if !cctx.Args().Present() {
|
|
|
|
return fmt.Errorf("must pass genesis car file")
|
|
|
|
}
|
|
|
|
bs := blockstore.NewBlockstore(datastore.NewMapDatastore())
|
|
|
|
|
2020-11-16 22:22:08 +00:00
|
|
|
cs := store.NewChainStore(bs, bs, datastore.NewMapDatastore(), nil, nil)
|
|
|
|
defer cs.Close() //nolint:errcheck
|
2020-08-21 01:10:11 +00:00
|
|
|
|
|
|
|
cf := cctx.Args().Get(0)
|
|
|
|
f, err := os.Open(cf)
|
|
|
|
if err != nil {
|
|
|
|
return xerrors.Errorf("opening the car file: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ts, err := cs.Import(f)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
sm := stmgr.NewStateManager(cs)
|
|
|
|
|
|
|
|
total, err := stmgr.CheckTotalFIL(context.TODO(), sm, ts)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-08-24 18:31:17 +00:00
|
|
|
fmt.Println("Genesis: ", ts.Key())
|
2020-08-22 03:58:39 +00:00
|
|
|
expFIL := big.Mul(big.NewInt(int64(build.FilBase)), big.NewInt(int64(build.FilecoinPrecision)))
|
|
|
|
fmt.Printf("Total FIL: %s", types.FIL(total))
|
|
|
|
if !expFIL.Equals(total) {
|
|
|
|
color.Red(" INCORRECT!")
|
|
|
|
}
|
|
|
|
fmt.Println()
|
|
|
|
|
|
|
|
cst := cbor.NewCborStore(bs)
|
|
|
|
|
2020-09-14 22:43:12 +00:00
|
|
|
stree, err := state.LoadStateTree(cst, ts.ParentState())
|
2020-08-22 03:58:39 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var accAddrs, msigAddrs []address.Address
|
|
|
|
kaccounts := make(map[address.Address]addrInfo)
|
|
|
|
kmultisigs := make(map[address.Address]msigInfo)
|
|
|
|
kminers := make(map[address.Address]minerInfo)
|
|
|
|
|
|
|
|
ctx := context.TODO()
|
2020-09-21 22:18:30 +00:00
|
|
|
store := adt.WrapStore(ctx, cst)
|
2020-08-22 03:58:39 +00:00
|
|
|
|
|
|
|
if err := stree.ForEach(func(addr address.Address, act *types.Actor) error {
|
2020-09-21 22:18:30 +00:00
|
|
|
switch {
|
2020-09-29 04:24:38 +00:00
|
|
|
case builtin.IsStorageMinerActor(act.Code):
|
2020-09-21 22:18:30 +00:00
|
|
|
_, err := miner.Load(store, act)
|
|
|
|
if err != nil {
|
|
|
|
return xerrors.Errorf("miner actor: %w", err)
|
2020-08-22 03:58:39 +00:00
|
|
|
}
|
2020-09-21 22:18:30 +00:00
|
|
|
// TODO: actually verify something here?
|
2020-08-22 03:58:39 +00:00
|
|
|
kminers[addr] = minerInfo{}
|
2020-09-29 04:24:38 +00:00
|
|
|
case builtin.IsMultisigActor(act.Code):
|
2020-09-21 22:18:30 +00:00
|
|
|
st, err := multisig.Load(store, act)
|
|
|
|
if err != nil {
|
2020-08-22 03:58:39 +00:00
|
|
|
return xerrors.Errorf("multisig actor: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-09-23 05:19:43 +00:00
|
|
|
signers, err := st.Signers()
|
|
|
|
if err != nil {
|
|
|
|
return xerrors.Errorf("multisig actor: %w", err)
|
|
|
|
}
|
|
|
|
threshold, err := st.Threshold()
|
|
|
|
if err != nil {
|
|
|
|
return xerrors.Errorf("multisig actor: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-08-22 03:58:39 +00:00
|
|
|
kmultisigs[addr] = msigInfo{
|
|
|
|
Balance: types.FIL(act.Balance),
|
2020-09-23 05:19:43 +00:00
|
|
|
Signers: signers,
|
|
|
|
Threshold: threshold,
|
2020-08-22 03:58:39 +00:00
|
|
|
}
|
|
|
|
msigAddrs = append(msigAddrs, addr)
|
2020-09-29 04:24:38 +00:00
|
|
|
case builtin.IsAccountActor(act.Code):
|
2020-09-21 22:18:30 +00:00
|
|
|
st, err := account.Load(store, act)
|
|
|
|
if err != nil {
|
|
|
|
// TODO: magik6k: this _used_ to log instead of failing, why?
|
|
|
|
return xerrors.Errorf("account actor %s: %w", addr, err)
|
|
|
|
}
|
|
|
|
pkaddr, err := st.PubkeyAddress()
|
|
|
|
if err != nil {
|
|
|
|
return xerrors.Errorf("failed to get actor pk address %s: %w", addr, err)
|
2020-08-22 03:58:39 +00:00
|
|
|
}
|
|
|
|
kaccounts[addr] = addrInfo{
|
2020-09-21 22:18:30 +00:00
|
|
|
Key: pkaddr,
|
2020-08-22 03:58:39 +00:00
|
|
|
Balance: types.FIL(act.Balance.Copy()),
|
|
|
|
}
|
|
|
|
accAddrs = append(accAddrs, addr)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Slice(accAddrs, func(i, j int) bool {
|
|
|
|
return accAddrs[i].String() < accAddrs[j].String()
|
|
|
|
})
|
|
|
|
|
|
|
|
sort.Slice(msigAddrs, func(i, j int) bool {
|
|
|
|
return msigAddrs[i].String() < msigAddrs[j].String()
|
|
|
|
})
|
|
|
|
|
|
|
|
fmt.Println("Account Actors:")
|
|
|
|
for _, acc := range accAddrs {
|
|
|
|
a := kaccounts[acc]
|
|
|
|
fmt.Printf("%s\t%s\t%s\n", acc, a.Key, a.Balance)
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Println("Multisig Actors:")
|
|
|
|
for _, acc := range msigAddrs {
|
|
|
|
m := kmultisigs[acc]
|
|
|
|
fmt.Printf("%s\t%s\t%d\t[", acc, m.Balance, m.Threshold)
|
|
|
|
for i, s := range m.Signers {
|
|
|
|
fmt.Print(s)
|
|
|
|
if i != len(m.Signers)-1 {
|
|
|
|
fmt.Print(",")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fmt.Printf("]\n")
|
|
|
|
}
|
2020-08-21 01:10:11 +00:00
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}
|