Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions addrcmd.go
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how frequently people are going to use this, my hope is if it's common enough someone will show up with a use case to determine how to handle it (e.g. if they're calling it repeatedly the type of cache that would be most useful). At the moment I don't do this more than occasionally for debugging so leaving it alone.

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)
Expand Down
12 changes: 9 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,15 @@ func main() {
{
Name: "addresses",
Usage: "<address>",
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",
Expand Down
81 changes: 80 additions & 1 deletion state.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"))
}
}
}
Comment on lines +187 to +200
Copy link
Owner Author

@aschmahmann aschmahmann Jun 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ribasushi is there a better way to do this? Ideally I'd be able to just use the latest version (or map a code/actor version to the init state struct), but looking for some alternative options here.

Some notes:

  1. This could probably be in a test (there should probably be a minimal testing setup 😅)
  2. More generally is the network version in the state tree somewhere such that it'd be easy enough to check that the code is out of date with the network and may/may not be accurate/safe until updated? (maybe existing code paths will already do this for me, but not sure if they all will/do now that we're not using the state manager code anymore)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What you are doing here locks you into "latest upgrade interval" only: you won't be able to query stuff before a particular epoch this way. Not sure this is the right way to go about this at all..

Ideally you recreate something like this (or have filoz put it in go-state-types where it belongs)
https://github.com/filecoin-project/lotus/blob/master/chain/actors/builtin/init/init.go#L32-L90

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you won't be able to query stuff before a particular epoch this way. Not sure this is the right way to go about this at all

Ah, I see. So I probably still need to keep this code in place (or with a test) so as to force updating the code when a new version comes out, but I should handle the historical versions as well with some sort of large map. Not sure if this would require committing to too many abstractions from the filoz folks since I'm operating on the IPLD object so I can load it into a parallel traversing HAMT which is lower level than the abstractions they currently have.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Afaik the HAMT never changed. I have a factored out code I will push tmrw, should make it cleaner...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a factored out code I will push tmrw, should make it cleaner...

@aschmahmann ☝️ it took 2 months, but here it is: #20


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 {
Expand Down