diff --git a/addrcmd.go b/addrcmd.go index 6432fa1..000bebd 100644 --- a/addrcmd.go +++ b/addrcmd.go @@ -1,7 +1,9 @@ package main import ( + "errors" "fmt" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" lchstate "github.com/filecoin-project/lotus/chain/state" @@ -57,8 +59,11 @@ func filToEthAddr(cctx *cli.Context) error { func filAddrs(cctx *cli.Context) error { args := cctx.Args() + ctx := cctx.Context actorAddrString := args.Get(0) + expensiveLookup := cctx.Bool("expensive") + was0xAddr := false var err error var eaddr ethtypes.EthAddress @@ -115,6 +120,28 @@ func filAddrs(cctx *cli.Context) error { // If it's a masked 0x address, return the f0 and if enabled the expensive reverse lookup for the fX address fmt.Println(addr) } + + if expensiveLookup { + var fXAddr address.Address + idValUint, err := address.IDFromAddress(addr) + if err != nil { + return err + } + idVal := int64(idValUint) + completionErr := fmt.Errorf("query complete") + if err := enumInit(ctx, bg, ts, func(id int64, actorAddr address.Address) error { + if idVal == id { + fXAddr = actorAddr + return completionErr + } + return nil + }); err == nil { + return fmt.Errorf("unable to perform reverse lookup for id address %s", addr) + } else if !errors.Is(err, completionErr) { + return err + } + fmt.Println(fXAddr) + } case address.Delegated: if !was0xAddr { fmt.Println(idAddr) diff --git a/main.go b/main.go index 196c97f..818a006 100644 --- a/main.go +++ b/main.go @@ -92,9 +92,15 @@ func main() { { Name: "addresses", Usage: "
", - Description: "Lists all the address types associated with an fX or 0x address. Note: will not back calculate fX addresses for f0 or masked ID 0x addresses", - Flags: append([]cli.Flag{}, stateFlags...), - Action: filAddrs, + Description: "Lists all the address types associated with an fX or 0x address", + Flags: append([]cli.Flag{ + &cli.BoolFlag{ + Name: "expensive", + Usage: "enables doing an expensive reverse lookup for resolving identity addresses into their robust addresses", + Value: false, + }, + }, stateFlags...), + Action: filAddrs, }, { Name: "msig-coins", diff --git a/state.go b/state.go index 572013c..255e442 100644 --- a/state.go +++ b/state.go @@ -10,12 +10,16 @@ import ( filaddr "github.com/filecoin-project/go-address" hamt "github.com/filecoin-project/go-hamt-ipld/v3" filabi "github.com/filecoin-project/go-state-types/abi" + actorstypes "github.com/filecoin-project/go-state-types/actors" filbig "github.com/filecoin-project/go-state-types/big" filbuiltin "github.com/filecoin-project/go-state-types/builtin" + _init13 "github.com/filecoin-project/go-state-types/builtin/v13/init" filadt "github.com/filecoin-project/go-state-types/builtin/v13/util/adt" + "github.com/filecoin-project/go-state-types/manifest" filstore "github.com/filecoin-project/go-state-types/store" - + "github.com/filecoin-project/lotus/chain/actors" lbi "github.com/filecoin-project/lotus/chain/actors/builtin" + lbiinit "github.com/filecoin-project/lotus/chain/actors/builtin/init" lbimsig "github.com/filecoin-project/lotus/chain/actors/builtin/multisig" lchstate "github.com/filecoin-project/lotus/chain/state" lchtypes "github.com/filecoin-project/lotus/chain/types" @@ -180,6 +184,81 @@ func enumActors(ctx context.Context, bg *blockGetter, ts *lchtypes.TipSet, actor return nil } +func init() { + latestInitCode := lbiinit.AllCodes()[len(lbiinit.AllCodes())-1] + if name, av, ok := actors.GetActorMetaByCode(latestInitCode); ok { + if name != manifest.InitKey { + panic(xerrors.Errorf("actor code is not init: %s", name)) + } + + if av != actorstypes.Version13 { + panic(xerrors.Errorf( + "the application is out of date with the network, please update to a later version," + + " or if this is the latest version file an issue to update the init actor version")) + } + } +} + +func enumInit(ctx context.Context, bg *blockGetter, ts *lchtypes.TipSet, initFunc func(id int64, addr filaddr.Address) error) error { + ast := filstore.WrapStore(ctx, ipldcbor.NewCborStore(bg)) + getManyAst := &getManyCborStore{ + BasicIpldStore: ipldcbor.NewCborStore(bg), + } + + var root lchtypes.StateRoot + // Try loading as a new-style state-tree (version/actors tuple). + if err := ast.Get(ctx, ts.ParentState(), &root); err != nil { + return err + } + + stateTree, err := lchstate.LoadStateTree(ipldcbor.NewCborStore(bg), ts.ParentState()) + if err != nil { + return err + } + + initActor, err := stateTree.GetActor(filbuiltin.InitActorAddr) + if err != nil { + return err + } + + var initRoot _init13.State + // Try loading as a new-style state-tree (version/actors tuple). + if err := ast.Get(ctx, initActor.Head, &initRoot); err != nil { + return err + } + + initHamt, err := hamt.LoadNode(ctx, getManyAst, initRoot.AddressMap, hamtOptions...) + if err != nil { + return err + } + + if err := initHamt.ForEachParallel(ctx, func(k string, val *cbg.Deferred) error { + var idCbg cbg.CborInt + addr, err := filaddr.NewFromBytes([]byte(k)) + if err != nil { + return xerrors.Errorf("invalid address (%x) found in state tree key: %w", []byte(k), err) + } + + err = idCbg.UnmarshalCBOR(bytes.NewReader(val.Raw)) + if err != nil { + return err + } + + if ctx.Err() != nil { + return ctx.Err() + } + + if err := initFunc(int64(idCbg), addr); err != nil { + return err + } + + return nil + }); err != nil { + return err + } + return nil +} + func getBalance(_ context.Context, bg *blockGetter, ts *lchtypes.TipSet, addr filaddr.Address) error { stateTree, err := lchstate.LoadStateTree(ipldcbor.NewCborStore(bg), ts.ParentState()) if err != nil {