From b24aab57679c66f219c8209f2e4b75c2112e4b82 Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Wed, 14 Dec 2022 00:10:35 -0500 Subject: [PATCH 1/8] Remove api.Wallet dependency from /chain/consensus --- api/api_wallet.go | 27 +---------------------- api/proxy_gen.go | 6 +++--- chain/consensus/filcns/mine.go | 6 +++--- chain/consensus/iface.go | 2 +- chain/gen/gen.go | 12 +++++------ chain/messagepool/check_test.go | 4 ++-- chain/messagepool/messagepool_test.go | 10 ++++----- chain/messagepool/selection_test.go | 4 ++-- chain/messagesigner/messagesigner.go | 4 ++-- chain/stmgr/forks_test.go | 5 ++--- chain/sync_test.go | 8 +++---- chain/types/mock/chain.go | 3 +-- chain/types/signedmessage.go | 31 +++++++++++++++++++++++++++ chain/wallet/ledger/ledger.go | 4 ++-- chain/wallet/multi.go | 2 +- chain/wallet/wallet.go | 2 +- cmd/lotus-wallet/interactive.go | 7 +++--- cmd/lotus-wallet/logged.go | 4 ++-- markets/storageadapter/client.go | 8 +++---- node/impl/full/wallet.go | 8 +++---- 20 files changed, 80 insertions(+), 77 deletions(-) diff --git a/api/api_wallet.go b/api/api_wallet.go index 973aaaf6d85..a7790df9f1c 100644 --- a/api/api_wallet.go +++ b/api/api_wallet.go @@ -9,37 +9,12 @@ import ( "github.com/filecoin-project/lotus/chain/types" ) -type MsgType string - -const ( - MTUnknown = "unknown" - - // Signing message CID. MsgMeta.Extra contains raw cbor message bytes - MTChainMsg = "message" - - // Signing a blockheader. signing raw cbor block bytes (MsgMeta.Extra is empty) - MTBlock = "block" - - // Signing a deal proposal. signing raw cbor proposal bytes (MsgMeta.Extra is empty) - MTDealProposal = "dealproposal" - - // TODO: Deals, Vouchers, VRF -) - -type MsgMeta struct { - Type MsgType - - // Additional data related to what is signed. Should be verifiable with the - // signed bytes (e.g. CID(Extra).Bytes() == toSign) - Extra []byte -} - type Wallet interface { WalletNew(context.Context, types.KeyType) (address.Address, error) //perm:admin WalletHas(context.Context, address.Address) (bool, error) //perm:admin WalletList(context.Context) ([]address.Address, error) //perm:admin - WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta MsgMeta) (*crypto.Signature, error) //perm:admin + WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta types.MsgSigningMeta) (*crypto.Signature, error) //perm:admin WalletExport(context.Context, address.Address) (*types.KeyInfo, error) //perm:admin WalletImport(context.Context, *types.KeyInfo) (address.Address, error) //perm:admin diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 7d0efb3fd6f..89618b1a4b1 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -1008,7 +1008,7 @@ type WalletStruct struct { WalletNew func(p0 context.Context, p1 types.KeyType) (address.Address, error) `perm:"admin"` - WalletSign func(p0 context.Context, p1 address.Address, p2 []byte, p3 MsgMeta) (*crypto.Signature, error) `perm:"admin"` + WalletSign func(p0 context.Context, p1 address.Address, p2 []byte, p3 types.MsgSigningMeta) (*crypto.Signature, error) `perm:"admin"` } } @@ -5936,14 +5936,14 @@ func (s *WalletStub) WalletNew(p0 context.Context, p1 types.KeyType) (address.Ad return *new(address.Address), ErrNotSupported } -func (s *WalletStruct) WalletSign(p0 context.Context, p1 address.Address, p2 []byte, p3 MsgMeta) (*crypto.Signature, error) { +func (s *WalletStruct) WalletSign(p0 context.Context, p1 address.Address, p2 []byte, p3 types.MsgSigningMeta) (*crypto.Signature, error) { if s.Internal.WalletSign == nil { return nil, ErrNotSupported } return s.Internal.WalletSign(p0, p1, p2, p3) } -func (s *WalletStub) WalletSign(p0 context.Context, p1 address.Address, p2 []byte, p3 MsgMeta) (*crypto.Signature, error) { +func (s *WalletStub) WalletSign(p0 context.Context, p1 address.Address, p2 []byte, p3 types.MsgSigningMeta) (*crypto.Signature, error) { return nil, ErrNotSupported } diff --git a/chain/consensus/filcns/mine.go b/chain/consensus/filcns/mine.go index 9924531782b..0c80161cc3f 100644 --- a/chain/consensus/filcns/mine.go +++ b/chain/consensus/filcns/mine.go @@ -14,7 +14,7 @@ import ( "github.com/filecoin-project/lotus/chain/types" ) -func (filec *FilecoinEC) CreateBlock(ctx context.Context, w api.Wallet, bt *api.BlockTemplate) (*types.FullBlock, error) { +func (filec *FilecoinEC) CreateBlock(ctx context.Context, w types.Signer, bt *api.BlockTemplate) (*types.FullBlock, error) { pts, err := filec.sm.ChainStore().LoadTipSet(ctx, bt.Parents) if err != nil { return nil, xerrors.Errorf("failed to load parent tipset: %w", err) @@ -121,8 +121,8 @@ func (filec *FilecoinEC) CreateBlock(ctx context.Context, w api.Wallet, bt *api. return nil, xerrors.Errorf("failed to get signing bytes for block: %w", err) } - sig, err := w.WalletSign(ctx, worker, nosigbytes, api.MsgMeta{ - Type: api.MTBlock, + sig, err := w.WalletSign(ctx, worker, nosigbytes, types.MsgSigningMeta{ + Type: types.MTBlock, }) if err != nil { return nil, xerrors.Errorf("failed to sign new block: %w", err) diff --git a/chain/consensus/iface.go b/chain/consensus/iface.go index 06dc0a11338..a75aba336fd 100644 --- a/chain/consensus/iface.go +++ b/chain/consensus/iface.go @@ -16,5 +16,5 @@ type Consensus interface { ValidateBlockPubsub(ctx context.Context, self bool, msg *pubsub.Message) (pubsub.ValidationResult, string) IsEpochBeyondCurrMax(epoch abi.ChainEpoch) bool - CreateBlock(ctx context.Context, w api.Wallet, bt *api.BlockTemplate) (*types.FullBlock, error) + CreateBlock(ctx context.Context, s types.Signer, bt *api.BlockTemplate) (*types.FullBlock, error) } diff --git a/chain/gen/gen.go b/chain/gen/gen.go index fe748020237..4a9162c6a6b 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -387,8 +387,8 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add } sf := func(ctx context.Context, a address.Address, i []byte) (*crypto.Signature, error) { - return cg.w.WalletSign(ctx, a, i, api.MsgMeta{ - Type: api.MTUnknown, + return cg.w.WalletSign(ctx, a, i, types.MsgSigningMeta{ + Type: types.MTUnknown, }) } @@ -558,8 +558,8 @@ func getRandomMessages(cg *ChainGen) ([]*types.SignedMessage, error) { GasPremium: types.NewInt(0), } - sig, err := cg.w.WalletSign(context.TODO(), cg.banker, msg.Cid().Bytes(), api.MsgMeta{ - Type: api.MTUnknown, // testing + sig, err := cg.w.WalletSign(context.TODO(), cg.banker, msg.Cid().Bytes(), types.MsgSigningMeta{ + Type: types.MTUnknown, // testing }) if err != nil { return nil, err @@ -610,8 +610,8 @@ func (mca mca) MinerGetBaseInfo(ctx context.Context, maddr address.Address, epoc } func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*crypto.Signature, error) { - return mca.w.WalletSign(ctx, a, v, api.MsgMeta{ - Type: api.MTUnknown, + return mca.w.WalletSign(ctx, a, v, types.MsgSigningMeta{ + Type: types.MTUnknown, }) } diff --git a/chain/messagepool/check_test.go b/chain/messagepool/check_test.go index 8458bdb0f6b..275c54f03ad 100644 --- a/chain/messagepool/check_test.go +++ b/chain/messagepool/check_test.go @@ -123,7 +123,7 @@ func TestCheckPendingMessages(t *testing.T) { Params: make([]byte, 2<<10), } - sig, err := w.WalletSign(context.TODO(), sender, msg.Cid().Bytes(), api.MsgMeta{}) + sig, err := w.WalletSign(context.TODO(), sender, msg.Cid().Bytes(), types.MsgSigningMeta{}) if err != nil { panic(err) } @@ -180,7 +180,7 @@ func TestCheckReplaceMessages(t *testing.T) { Params: make([]byte, 2<<10), } - sig, err := w.WalletSign(context.TODO(), sender, msg.Cid().Bytes(), api.MsgMeta{}) + sig, err := w.WalletSign(context.TODO(), sender, msg.Cid().Bytes(), types.MsgSigningMeta{}) if err != nil { panic(err) } diff --git a/chain/messagepool/messagepool_test.go b/chain/messagepool/messagepool_test.go index 35e13e13d69..17227309546 100644 --- a/chain/messagepool/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -305,7 +305,7 @@ func TestCheckMessageBig(t *testing.T) { Params: make([]byte, 41<<10), // 41KiB payload } - sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), api.MsgMeta{}) + sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), types.MsgSigningMeta{}) if err != nil { panic(err) } @@ -328,7 +328,7 @@ func TestCheckMessageBig(t *testing.T) { Params: make([]byte, 64<<10), // 64KiB payload } - sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), api.MsgMeta{}) + sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), types.MsgSigningMeta{}) if err != nil { panic(err) } @@ -804,7 +804,7 @@ func TestMessageBelowMinGasFee(t *testing.T) { Params: make([]byte, 32<<10), } - sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), api.MsgMeta{}) + sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), types.MsgSigningMeta{}) if err != nil { panic(err) } @@ -852,7 +852,7 @@ func TestMessageValueTooHigh(t *testing.T) { Params: make([]byte, 32<<10), } - sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), api.MsgMeta{}) + sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), types.MsgSigningMeta{}) if err != nil { panic(err) } @@ -941,7 +941,7 @@ func TestAddMessageTwice(t *testing.T) { Params: make([]byte, 32<<10), } - sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), api.MsgMeta{}) + sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), types.MsgSigningMeta{}) if err != nil { panic(err) } diff --git a/chain/messagepool/selection_test.go b/chain/messagepool/selection_test.go index c3a5c6d6f3a..4e055c462cd 100644 --- a/chain/messagepool/selection_test.go +++ b/chain/messagepool/selection_test.go @@ -51,7 +51,7 @@ func makeTestMessage(w *wallet.LocalWallet, from, to address.Address, nonce uint GasFeeCap: types.NewInt(100 + gasPrice), GasPremium: types.NewInt(gasPrice), } - sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), api.MsgMeta{}) + sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), types.MsgSigningMeta{}) if err != nil { panic(err) } @@ -1587,7 +1587,7 @@ readLoop: m.Message.From = localActor m.Message.Nonce -= baseNonce - sig, err := w.WalletSign(context.TODO(), localActor, m.Message.Cid().Bytes(), api.MsgMeta{}) + sig, err := w.WalletSign(context.TODO(), localActor, m.Message.Cid().Bytes(), types.MsgSigningMeta{}) if err != nil { t.Fatal(err) } diff --git a/chain/messagesigner/messagesigner.go b/chain/messagesigner/messagesigner.go index 96457e9f872..3cc55dd88e7 100644 --- a/chain/messagesigner/messagesigner.go +++ b/chain/messagesigner/messagesigner.go @@ -71,8 +71,8 @@ func (ms *MessageSigner) SignMessage(ctx context.Context, msg *types.Message, sp return nil, xerrors.Errorf("serializing message: %w", err) } - sig, err := ms.wallet.WalletSign(ctx, msg.From, mb.Cid().Bytes(), api.MsgMeta{ - Type: api.MTChainMsg, + sig, err := ms.wallet.WalletSign(ctx, msg.From, mb.Cid().Bytes(), types.MsgSigningMeta{ + Type: types.MTChainMsg, Extra: mb.RawData(), }) if err != nil { diff --git a/chain/stmgr/forks_test.go b/chain/stmgr/forks_test.go index 98ab647c940..f4022c7fb93 100644 --- a/chain/stmgr/forks_test.go +++ b/chain/stmgr/forks_test.go @@ -25,7 +25,6 @@ import ( init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init" rt2 "github.com/filecoin-project/specs-actors/v2/actors/runtime" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -198,7 +197,7 @@ func TestForkHeightTriggers(t *testing.T) { Params: enc, GasLimit: types.TestGasLimit, } - sig, err := cg.Wallet().WalletSign(ctx, cg.Banker(), m.Cid().Bytes(), api.MsgMeta{}) + sig, err := cg.Wallet().WalletSign(ctx, cg.Banker(), m.Cid().Bytes(), types.MsgSigningMeta{}) if err != nil { t.Fatal(err) } @@ -226,7 +225,7 @@ func TestForkHeightTriggers(t *testing.T) { } nonce++ - sig, err := cg.Wallet().WalletSign(ctx, cg.Banker(), m.Cid().Bytes(), api.MsgMeta{}) + sig, err := cg.Wallet().WalletSign(ctx, cg.Banker(), m.Cid().Bytes(), types.MsgSigningMeta{}) if err != nil { return nil, err } diff --git a/chain/sync_test.go b/chain/sync_test.go index 18520a07fe4..0faf86588a2 100644 --- a/chain/sync_test.go +++ b/chain/sync_test.go @@ -701,7 +701,7 @@ func TestDuplicateNonce(t *testing.T) { GasPremium: types.NewInt(0), } - sig, err := tu.g.Wallet().WalletSign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes(), api.MsgMeta{}) + sig, err := tu.g.Wallet().WalletSign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes(), types.MsgSigningMeta{}) require.NoError(t, err) return &types.SignedMessage{ @@ -800,7 +800,7 @@ func TestBadNonce(t *testing.T) { GasPremium: types.NewInt(0), } - sig, err := tu.g.Wallet().WalletSign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes(), api.MsgMeta{}) + sig, err := tu.g.Wallet().WalletSign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes(), types.MsgSigningMeta{}) require.NoError(t, err) return &types.SignedMessage{ @@ -858,7 +858,7 @@ func TestMismatchedNoncesRobustID(t *testing.T) { GasPremium: types.NewInt(0), } - sig, err := tu.g.Wallet().WalletSign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes(), api.MsgMeta{}) + sig, err := tu.g.Wallet().WalletSign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes(), types.MsgSigningMeta{}) require.NoError(t, err) return &types.SignedMessage{ @@ -916,7 +916,7 @@ func TestMatchedNoncesRobustID(t *testing.T) { GasPremium: types.NewInt(0), } - sig, err := tu.g.Wallet().WalletSign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes(), api.MsgMeta{}) + sig, err := tu.g.Wallet().WalletSign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes(), types.MsgSigningMeta{}) require.NoError(t, err) return &types.SignedMessage{ diff --git a/chain/types/mock/chain.go b/chain/types/mock/chain.go index dcbcd85362c..158a34a9cc6 100644 --- a/chain/types/mock/chain.go +++ b/chain/types/mock/chain.go @@ -11,7 +11,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet" @@ -28,7 +27,7 @@ func Address(i uint64) address.Address { func MkMessage(from, to address.Address, nonce uint64, w *wallet.LocalWallet) *types.SignedMessage { msg := UnsignedMessage(from, to, nonce) - sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), api.MsgMeta{}) + sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), types.MsgSigningMeta{}) if err != nil { panic(err) } diff --git a/chain/types/signedmessage.go b/chain/types/signedmessage.go index 16853171464..40e07c07680 100644 --- a/chain/types/signedmessage.go +++ b/chain/types/signedmessage.go @@ -6,7 +6,9 @@ import ( block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + "golang.org/x/net/context" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" ) @@ -106,3 +108,32 @@ func (sm *SignedMessage) Size() int { func (sm *SignedMessage) VMMessage() *Message { return &sm.Message } + +type Signer interface { + WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta MsgSigningMeta) (*crypto.Signature, error) +} + +type MsgType string + +const ( + MTUnknown = "unknown" + + // Signing message CID. MsgSigningMeta.Extra contains raw cbor message bytes + MTChainMsg = "message" + + // Signing a blockheader. signing raw cbor block bytes (MsgSigningMeta.Extra is empty) + MTBlock = "block" + + // Signing a deal proposal. signing raw cbor proposal bytes (MsgSigningMeta.Extra is empty) + MTDealProposal = "dealproposal" + + // TODO: Deals, Vouchers, VRF +) + +type MsgSigningMeta struct { + Type MsgType + + // Additional data related to what is signed. Should be verifiable with the + // signed bytes (e.g. CID(Extra).Bytes() == toSign) + Extra []byte +} diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index 5279389de81..1b46fe53fec 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -38,7 +38,7 @@ type LedgerKeyInfo struct { var _ api.Wallet = (*LedgerWallet)(nil) -func (lw LedgerWallet) WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta api.MsgMeta) (*crypto.Signature, error) { +func (lw LedgerWallet) WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta types.MsgSigningMeta) (*crypto.Signature, error) { ki, err := lw.getKeyInfo(ctx, signer) if err != nil { return nil, err @@ -49,7 +49,7 @@ func (lw LedgerWallet) WalletSign(ctx context.Context, signer address.Address, t return nil, err } defer fl.Close() // nolint:errcheck - if meta.Type != api.MTChainMsg { + if meta.Type != types.MTChainMsg { return nil, fmt.Errorf("ledger can only sign chain messages") } diff --git a/chain/wallet/multi.go b/chain/wallet/multi.go index a88475c2e3e..b51e1ea90ef 100644 --- a/chain/wallet/multi.go +++ b/chain/wallet/multi.go @@ -114,7 +114,7 @@ func (m MultiWallet) WalletList(ctx context.Context) ([]address.Address, error) return out, nil } -func (m MultiWallet) WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta api.MsgMeta) (*crypto.Signature, error) { +func (m MultiWallet) WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta types.MsgSigningMeta) (*crypto.Signature, error) { w, err := m.find(ctx, signer, m.Remote, m.Ledger, m.Local) if err != nil { return nil, err diff --git a/chain/wallet/wallet.go b/chain/wallet/wallet.go index 32a94d3b28d..a2482bff891 100644 --- a/chain/wallet/wallet.go +++ b/chain/wallet/wallet.go @@ -61,7 +61,7 @@ func KeyWallet(keys ...*key.Key) *LocalWallet { } } -func (w *LocalWallet) WalletSign(ctx context.Context, addr address.Address, msg []byte, meta api.MsgMeta) (*crypto.Signature, error) { +func (w *LocalWallet) WalletSign(ctx context.Context, addr address.Address, msg []byte, meta types.MsgSigningMeta) (*crypto.Signature, error) { ki, err := w.findKey(addr) if err != nil { return nil, err diff --git a/cmd/lotus-wallet/interactive.go b/cmd/lotus-wallet/interactive.go index 40c3f892231..331136eddf7 100644 --- a/cmd/lotus-wallet/interactive.go +++ b/cmd/lotus-wallet/interactive.go @@ -19,7 +19,6 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api/v0api" "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/builtin/multisig" @@ -57,7 +56,7 @@ func (c *InteractiveWallet) WalletList(ctx context.Context) ([]address.Address, return c.under.WalletList(ctx) } -func (c *InteractiveWallet) WalletSign(ctx context.Context, k address.Address, msg []byte, meta api.MsgMeta) (*crypto.Signature, error) { +func (c *InteractiveWallet) WalletSign(ctx context.Context, k address.Address, msg []byte, meta types.MsgSigningMeta) (*crypto.Signature, error) { err := c.accept(func() error { fmt.Println("-----") fmt.Println("ACTION: WalletSign - Sign a message/deal") @@ -65,7 +64,7 @@ func (c *InteractiveWallet) WalletSign(ctx context.Context, k address.Address, m fmt.Printf("TYPE: %s\n", meta.Type) switch meta.Type { - case api.MTChainMsg: + case types.MTChainMsg: var cmsg types.Message if err := cmsg.UnmarshalCBOR(bytes.NewReader(meta.Extra)); err != nil { return xerrors.Errorf("unmarshalling message: %w", err) @@ -137,7 +136,7 @@ func (c *InteractiveWallet) WalletSign(ctx context.Context, k address.Address, m fmt.Println("Params: No chain node connection, can't decode params") } - case api.MTDealProposal: + case types.MTDealProposal: return xerrors.Errorf("TODO") // TODO default: log.Infow("WalletSign", "address", k, "type", meta.Type) diff --git a/cmd/lotus-wallet/logged.go b/cmd/lotus-wallet/logged.go index 4f07d6ae46e..5f64bf879fa 100644 --- a/cmd/lotus-wallet/logged.go +++ b/cmd/lotus-wallet/logged.go @@ -37,9 +37,9 @@ func (c *LoggedWallet) WalletList(ctx context.Context) ([]address.Address, error return c.under.WalletList(ctx) } -func (c *LoggedWallet) WalletSign(ctx context.Context, k address.Address, msg []byte, meta api.MsgMeta) (*crypto.Signature, error) { +func (c *LoggedWallet) WalletSign(ctx context.Context, k address.Address, msg []byte, meta types.MsgSigningMeta) (*crypto.Signature, error) { switch meta.Type { - case api.MTChainMsg: + case types.MTChainMsg: var cmsg types.Message if err := cmsg.UnmarshalCBOR(bytes.NewReader(meta.Extra)); err != nil { return nil, xerrors.Errorf("unmarshalling message: %w", err) diff --git a/markets/storageadapter/client.go b/markets/storageadapter/client.go index eaff4e166a3..38be0159109 100644 --- a/markets/storageadapter/client.go +++ b/markets/storageadapter/client.go @@ -379,8 +379,8 @@ func (c *ClientNodeAdapter) SignProposal(ctx context.Context, signer address.Add return nil, err } - sig, err := c.Wallet.WalletSign(ctx, signer, buf, api.MsgMeta{ - Type: api.MTDealProposal, + sig, err := c.Wallet.WalletSign(ctx, signer, buf, types.MsgSigningMeta{ + Type: types.MTDealProposal, }) if err != nil { return nil, err @@ -434,8 +434,8 @@ func (c *ClientNodeAdapter) SignBytes(ctx context.Context, signer address.Addres return nil, err } - localSignature, err := c.Wallet.WalletSign(ctx, signer, b, api.MsgMeta{ - Type: api.MTUnknown, // TODO: pass type here + localSignature, err := c.Wallet.WalletSign(ctx, signer, b, types.MsgSigningMeta{ + Type: types.MTUnknown, // TODO: pass type here }) if err != nil { return nil, err diff --git a/node/impl/full/wallet.go b/node/impl/full/wallet.go index ae2550d77c7..aa610046612 100644 --- a/node/impl/full/wallet.go +++ b/node/impl/full/wallet.go @@ -40,8 +40,8 @@ func (a *WalletAPI) WalletSign(ctx context.Context, k address.Address, msg []byt if err != nil { return nil, xerrors.Errorf("failed to resolve ID address: %w", keyAddr) } - return a.Wallet.WalletSign(ctx, keyAddr, msg, api.MsgMeta{ - Type: api.MTUnknown, + return a.Wallet.WalletSign(ctx, keyAddr, msg, types.MsgSigningMeta{ + Type: types.MTUnknown, }) } @@ -56,8 +56,8 @@ func (a *WalletAPI) WalletSignMessage(ctx context.Context, k address.Address, ms return nil, xerrors.Errorf("serializing message: %w", err) } - sig, err := a.Wallet.WalletSign(ctx, keyAddr, mb.Cid().Bytes(), api.MsgMeta{ - Type: api.MTChainMsg, + sig, err := a.Wallet.WalletSign(ctx, keyAddr, mb.Cid().Bytes(), types.MsgSigningMeta{ + Type: types.MTChainMsg, Extra: mb.RawData(), }) if err != nil { From 410c1c68586e436e1b22a72f2d96965e41cd4646 Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Wed, 14 Dec 2022 00:25:01 -0500 Subject: [PATCH 2/8] Move InvocResult and MsgGasCost to chain/types --- api/api_full.go | 27 +++---------------- api/eth_types.go | 3 ++- api/mocks/mock_full.go | 8 +++--- api/proxy_gen.go | 12 ++++----- api/v0api/full.go | 4 +-- api/v0api/proxy_gen.go | 12 ++++----- api/v0api/v0mocks/mock_full.go | 8 +++--- build/openrpc/full.json.gz | Bin 31071 -> 31072 bytes chain/stmgr/call.go | 13 +++++---- chain/stmgr/execute.go | 5 ++-- chain/stmgr/rpc/rpcstatemanager.go | 2 +- chain/stmgr/stmgr.go | 2 +- chain/stmgr/tracers.go | 5 ++-- chain/stmgr/utils.go | 7 +++-- chain/types/execresult.go | 25 +++++++++++++++++ cli/state.go | 2 +- cmd/lotus-bench/import.go | 7 +++-- markets/storageadapter/dealpublisher.go | 2 +- markets/storageadapter/dealpublisher_test.go | 4 +-- node/impl/full/eth.go | 6 ++--- node/impl/full/gas.go | 2 +- node/impl/full/state.go | 6 ++--- paychmgr/manager.go | 2 +- paychmgr/mock_test.go | 6 ++--- paychmgr/paych_test.go | 7 +++-- 25 files changed, 88 insertions(+), 89 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 93ee6f43d84..c2e8ba3b122 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -405,7 +405,7 @@ type FullNode interface { // StateCall applies the message to the tipset's parent state. The // message is not applied on-top-of the messages in the passed-in // tipset. - StateCall(context.Context, *types.Message, types.TipSetKey) (*InvocResult, error) //perm:read + StateCall(context.Context, *types.Message, types.TipSetKey) (*types.InvocResult, error) //perm:read // StateReplay replays a given message, assuming it was included in a block in the specified tipset. // // If a tipset key is provided, and a replacing message is not found on chain, @@ -423,7 +423,7 @@ type FullNode interface { // A replacing message is a message with a different CID, any of Gas values, and // different signature, but with all other parameters matching (source/destination, // nonce, params, etc.) - StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error) //perm:read + StateReplay(context.Context, types.TipSetKey, cid.Cid) (*types.InvocResult, error) //perm:read // StateGetActor returns the indicated actor's nonce and balance. StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) //perm:read // StateReadState returns the indicated actor's state. @@ -882,17 +882,6 @@ type MsgLookup struct { Height abi.ChainEpoch } -type MsgGasCost struct { - Message cid.Cid // Can be different than requested, in case it was replaced, but only gas values changed - GasUsed abi.TokenAmount - BaseFeeBurn abi.TokenAmount - OverEstimationBurn abi.TokenAmount - MinerPenalty abi.TokenAmount - MinerTip abi.TokenAmount - Refund abi.TokenAmount - TotalCost abi.TokenAmount -} - // BlsMessages[x].cid = Cids[x] // SecpkMessages[y].cid = Cids[BlsMessages.length + y] type BlockMessages struct { @@ -1058,16 +1047,6 @@ type RetrievalOrder struct { type RemoteStoreID = uuid.UUID -type InvocResult struct { - MsgCid cid.Cid - Msg *types.Message - MsgRct *types.MessageReceipt - GasCost MsgGasCost - ExecutionTrace types.ExecutionTrace - Error string - Duration time.Duration -} - type MethodCall struct { types.MessageReceipt Error string @@ -1172,7 +1151,7 @@ type MpoolUpdate struct { type ComputeStateOutput struct { Root cid.Cid - Trace []*InvocResult + Trace []*types.InvocResult } type DealCollateralBounds struct { diff --git a/api/eth_types.go b/api/eth_types.go index ffce16756d7..c5de37bd80a 100644 --- a/api/eth_types.go +++ b/api/eth_types.go @@ -21,6 +21,7 @@ import ( "github.com/filecoin-project/go-state-types/builtin/v10/eam" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/types" ) type EthUint64 uint64 @@ -198,7 +199,7 @@ type EthTxReceipt struct { Logs []string `json:"logs"` } -func NewEthTxReceipt(tx EthTx, lookup *MsgLookup, replay *InvocResult) (EthTxReceipt, error) { +func NewEthTxReceipt(tx EthTx, lookup *MsgLookup, replay *types.InvocResult) (EthTxReceipt, error) { receipt := EthTxReceipt{ TransactionHash: tx.Hash, TransactionIndex: tx.TransactionIndex, diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 6ae62728b02..f32a2079b11 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -2739,10 +2739,10 @@ func (mr *MockFullNodeMockRecorder) StateAllMinerFaults(arg0, arg1, arg2 interfa } // StateCall mocks base method. -func (m *MockFullNode) StateCall(arg0 context.Context, arg1 *types.Message, arg2 types.TipSetKey) (*api.InvocResult, error) { +func (m *MockFullNode) StateCall(arg0 context.Context, arg1 *types.Message, arg2 types.TipSetKey) (*types.InvocResult, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateCall", arg0, arg1, arg2) - ret0, _ := ret[0].(*api.InvocResult) + ret0, _ := ret[0].(*types.InvocResult) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -3414,10 +3414,10 @@ func (mr *MockFullNodeMockRecorder) StateReadState(arg0, arg1, arg2 interface{}) } // StateReplay mocks base method. -func (m *MockFullNode) StateReplay(arg0 context.Context, arg1 types.TipSetKey, arg2 cid.Cid) (*api.InvocResult, error) { +func (m *MockFullNode) StateReplay(arg0 context.Context, arg1 types.TipSetKey, arg2 cid.Cid) (*types.InvocResult, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateReplay", arg0, arg1, arg2) - ret0, _ := ret[0].(*api.InvocResult) + ret0, _ := ret[0].(*types.InvocResult) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 89618b1a4b1..f7d2b022e12 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -403,7 +403,7 @@ type FullNodeStruct struct { StateAllMinerFaults func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) ([]*Fault, error) `perm:"read"` - StateCall func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*InvocResult, error) `perm:"read"` + StateCall func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*types.InvocResult, error) `perm:"read"` StateChangedActors func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (map[string]types.Actor, error) `perm:"read"` @@ -493,7 +493,7 @@ type FullNodeStruct struct { StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*ActorState, error) `perm:"read"` - StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*InvocResult, error) `perm:"read"` + StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*types.InvocResult, error) `perm:"read"` StateSearchMsg func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `perm:"read"` @@ -2856,14 +2856,14 @@ func (s *FullNodeStub) StateAllMinerFaults(p0 context.Context, p1 abi.ChainEpoch return *new([]*Fault), ErrNotSupported } -func (s *FullNodeStruct) StateCall(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*InvocResult, error) { +func (s *FullNodeStruct) StateCall(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*types.InvocResult, error) { if s.Internal.StateCall == nil { return nil, ErrNotSupported } return s.Internal.StateCall(p0, p1, p2) } -func (s *FullNodeStub) StateCall(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*InvocResult, error) { +func (s *FullNodeStub) StateCall(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*types.InvocResult, error) { return nil, ErrNotSupported } @@ -3351,14 +3351,14 @@ func (s *FullNodeStub) StateReadState(p0 context.Context, p1 address.Address, p2 return nil, ErrNotSupported } -func (s *FullNodeStruct) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*InvocResult, error) { +func (s *FullNodeStruct) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*types.InvocResult, error) { if s.Internal.StateReplay == nil { return nil, ErrNotSupported } return s.Internal.StateReplay(p0, p1, p2) } -func (s *FullNodeStub) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*InvocResult, error) { +func (s *FullNodeStub) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*types.InvocResult, error) { return nil, ErrNotSupported } diff --git a/api/v0api/full.go b/api/v0api/full.go index 87d5cba4e99..6d4ca066281 100644 --- a/api/v0api/full.go +++ b/api/v0api/full.go @@ -384,7 +384,7 @@ type FullNode interface { // StateCall applies the message to the tipset's parent state. The // message is not applied on-top-of the messages in the passed-in // tipset. - StateCall(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error) //perm:read + StateCall(context.Context, *types.Message, types.TipSetKey) (*types.InvocResult, error) //perm:read // StateReplay replays a given message, assuming it was included in a block in the specified tipset. // // If a tipset key is provided, and a replacing message is not found on chain, @@ -402,7 +402,7 @@ type FullNode interface { // A replacing message is a message with a different CID, any of Gas values, and // different signature, but with all other parameters matching (source/destination, // nonce, params, etc.) - StateReplay(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) //perm:read + StateReplay(context.Context, types.TipSetKey, cid.Cid) (*types.InvocResult, error) //perm:read // StateGetActor returns the indicated actor's nonce and balance. StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) //perm:read // StateReadState returns the indicated actor's state. diff --git a/api/v0api/proxy_gen.go b/api/v0api/proxy_gen.go index b1a07dacc18..40eeadd215d 100644 --- a/api/v0api/proxy_gen.go +++ b/api/v0api/proxy_gen.go @@ -264,7 +264,7 @@ type FullNodeStruct struct { StateAllMinerFaults func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) ([]*api.Fault, error) `perm:"read"` - StateCall func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*api.InvocResult, error) `perm:"read"` + StateCall func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*types.InvocResult, error) `perm:"read"` StateChangedActors func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (map[string]types.Actor, error) `perm:"read"` @@ -346,7 +346,7 @@ type FullNodeStruct struct { StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*api.ActorState, error) `perm:"read"` - StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*api.InvocResult, error) `perm:"read"` + StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*types.InvocResult, error) `perm:"read"` StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) `perm:"read"` @@ -1727,14 +1727,14 @@ func (s *FullNodeStub) StateAllMinerFaults(p0 context.Context, p1 abi.ChainEpoch return *new([]*api.Fault), ErrNotSupported } -func (s *FullNodeStruct) StateCall(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*api.InvocResult, error) { +func (s *FullNodeStruct) StateCall(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*types.InvocResult, error) { if s.Internal.StateCall == nil { return nil, ErrNotSupported } return s.Internal.StateCall(p0, p1, p2) } -func (s *FullNodeStub) StateCall(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*api.InvocResult, error) { +func (s *FullNodeStub) StateCall(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*types.InvocResult, error) { return nil, ErrNotSupported } @@ -2178,14 +2178,14 @@ func (s *FullNodeStub) StateReadState(p0 context.Context, p1 address.Address, p2 return nil, ErrNotSupported } -func (s *FullNodeStruct) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*api.InvocResult, error) { +func (s *FullNodeStruct) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*types.InvocResult, error) { if s.Internal.StateReplay == nil { return nil, ErrNotSupported } return s.Internal.StateReplay(p0, p1, p2) } -func (s *FullNodeStub) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*api.InvocResult, error) { +func (s *FullNodeStub) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*types.InvocResult, error) { return nil, ErrNotSupported } diff --git a/api/v0api/v0mocks/mock_full.go b/api/v0api/v0mocks/mock_full.go index 3aff979ff65..32280693bc2 100644 --- a/api/v0api/v0mocks/mock_full.go +++ b/api/v0api/v0mocks/mock_full.go @@ -2234,10 +2234,10 @@ func (mr *MockFullNodeMockRecorder) StateAllMinerFaults(arg0, arg1, arg2 interfa } // StateCall mocks base method. -func (m *MockFullNode) StateCall(arg0 context.Context, arg1 *types.Message, arg2 types.TipSetKey) (*api.InvocResult, error) { +func (m *MockFullNode) StateCall(arg0 context.Context, arg1 *types.Message, arg2 types.TipSetKey) (*types.InvocResult, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateCall", arg0, arg1, arg2) - ret0, _ := ret[0].(*api.InvocResult) + ret0, _ := ret[0].(*types.InvocResult) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -2849,10 +2849,10 @@ func (mr *MockFullNodeMockRecorder) StateReadState(arg0, arg1, arg2 interface{}) } // StateReplay mocks base method. -func (m *MockFullNode) StateReplay(arg0 context.Context, arg1 types.TipSetKey, arg2 cid.Cid) (*api.InvocResult, error) { +func (m *MockFullNode) StateReplay(arg0 context.Context, arg1 types.TipSetKey, arg2 cid.Cid) (*types.InvocResult, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateReplay", arg0, arg1, arg2) - ret0, _ := ret[0].(*api.InvocResult) + ret0, _ := ret[0].(*types.InvocResult) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 76cee3b6a7aff4af721efa86197c1f601692d1a5..01c7a7aacb55dc13232be308df626e29222b38c3 100644 GIT binary patch delta 12438 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 gdq4X)$d07U(80RRC1|8T{2Ia(wJ0PO(*1ONa4 diff --git a/chain/stmgr/call.go b/chain/stmgr/call.go index 69f78f69910..4d7a149df3e 100644 --- a/chain/stmgr/call.go +++ b/chain/stmgr/call.go @@ -16,7 +16,6 @@ import ( "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/network" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/rand" @@ -30,7 +29,7 @@ var ErrExpensiveFork = errors.New("refusing explicit call due to state fork at e // Call applies the given message to the given tipset's parent state, at the epoch following the // tipset's parent. In the presence of null blocks, the height at which the message is invoked may // be less than the specified tipset. -func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error) { +func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.InvocResult, error) { if msg.GasLimit == 0 { msg.GasLimit = build.BlockGasLimit } @@ -48,7 +47,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types. } // CallWithGas calculates the state for a given tipset, and then applies the given message on top of that state. -func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, priorMsgs []types.ChainMsg, ts *types.TipSet) (*api.InvocResult, error) { +func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, priorMsgs []types.ChainMsg, ts *types.TipSet) (*types.InvocResult, error) { return sm.callInternal(ctx, msg, priorMsgs, ts, cid.Undef, sm.GetNetworkVersion, true) } @@ -56,7 +55,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri // This should mostly be used for gas modelling on a migrated state. // Tipset here is not needed because stateCid and network version fully describe execution we want. The internal function // will get the heaviest tipset for use for things like basefee, which we don't really care about here. -func (sm *StateManager) CallAtStateAndVersion(ctx context.Context, msg *types.Message, stateCid cid.Cid, v network.Version) (*api.InvocResult, error) { +func (sm *StateManager) CallAtStateAndVersion(ctx context.Context, msg *types.Message, stateCid cid.Cid, v network.Version) (*types.InvocResult, error) { nvGetter := func(context.Context, abi.ChainEpoch) network.Version { return v } @@ -67,7 +66,7 @@ func (sm *StateManager) CallAtStateAndVersion(ctx context.Context, msg *types.Me // - If no tipset is specified, the first tipset without an expensive migration or one in its parent is used. // - If executing a message at a given tipset or its parent would trigger an expensive migration, the call will // fail with ErrExpensiveFork. -func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, priorMsgs []types.ChainMsg, ts *types.TipSet, stateCid cid.Cid, nvGetter rand.NetworkVersionGetter, checkGas bool) (*api.InvocResult, error) { +func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, priorMsgs []types.ChainMsg, ts *types.TipSet, stateCid cid.Cid, nvGetter rand.NetworkVersionGetter, checkGas bool) (*types.InvocResult, error) { ctx, span := trace.StartSpan(ctx, "statemanager.callInternal") defer span.End() @@ -198,7 +197,7 @@ func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, pr } var ret *vm.ApplyRet - var gasInfo api.MsgGasCost + var gasInfo types.MsgGasCost if checkGas { fromKey, err := sm.ResolveToKeyAddress(ctx, msg.From, ts) if err != nil { @@ -245,7 +244,7 @@ func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, pr errs = ret.ActorErr.Error() } - return &api.InvocResult{ + return &types.InvocResult{ MsgCid: msg.Cid(), Msg: msg, MsgRct: &ret.MessageReceipt, diff --git a/chain/stmgr/execute.go b/chain/stmgr/execute.go index 60ee069d04d..e113e39c5ce 100644 --- a/chain/stmgr/execute.go +++ b/chain/stmgr/execute.go @@ -7,7 +7,6 @@ import ( "github.com/ipfs/go-cid" "go.opencensus.io/trace" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" ) @@ -73,8 +72,8 @@ func (sm *StateManager) ExecutionTraceWithMonitor(ctx context.Context, ts *types return st, err } -func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (cid.Cid, []*api.InvocResult, error) { - var invocTrace []*api.InvocResult +func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (cid.Cid, []*types.InvocResult, error) { + var invocTrace []*types.InvocResult st, err := sm.ExecutionTraceWithMonitor(ctx, ts, &InvocationTracer{trace: &invocTrace}) if err != nil { return cid.Undef, nil, err diff --git a/chain/stmgr/rpc/rpcstatemanager.go b/chain/stmgr/rpc/rpcstatemanager.go index 2c9893cc0d0..7501c00bc24 100644 --- a/chain/stmgr/rpc/rpcstatemanager.go +++ b/chain/stmgr/rpc/rpcstatemanager.go @@ -52,7 +52,7 @@ func (s *RPCStateManager) ResolveToKeyAddress(ctx context.Context, addr address. return s.gapi.StateAccountKey(ctx, addr, ts.Key()) } -func (s *RPCStateManager) Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error) { +func (s *RPCStateManager) Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.InvocResult, error) { return nil, xerrors.Errorf("RPCStateManager does not implement StateManager.Call") } diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index b990555fe69..46190a0e21b 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -38,7 +38,7 @@ const ReceiptAmtBitwidth = 3 var log = logging.Logger("statemgr") type StateManagerAPI interface { - Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error) + Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.InvocResult, error) GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error) LoadActorTsk(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error) LookupID(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) diff --git a/chain/stmgr/tracers.go b/chain/stmgr/tracers.go index 408205de0ac..647c595b37c 100644 --- a/chain/stmgr/tracers.go +++ b/chain/stmgr/tracers.go @@ -5,7 +5,6 @@ import ( "github.com/ipfs/go-cid" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" ) @@ -18,11 +17,11 @@ type ExecMonitor interface { var _ ExecMonitor = (*InvocationTracer)(nil) type InvocationTracer struct { - trace *[]*api.InvocResult + trace *[]*types.InvocResult } func (i *InvocationTracer) MessageApplied(ctx context.Context, ts *types.TipSet, mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet, implicit bool) error { - ir := &api.InvocResult{ + ir := &types.InvocResult{ MsgCid: mcid, Msg: msg, MsgRct: &ret.MessageReceipt, diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index c93267d50f8..25bfebc0ad4 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -16,7 +16,6 @@ import ( "github.com/filecoin-project/go-state-types/manifest" gstStore "github.com/filecoin-project/go-state-types/store" - "github.com/filecoin-project/lotus/api" init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init" "github.com/filecoin-project/lotus/chain/actors/builtin/system" "github.com/filecoin-project/lotus/chain/actors/policy" @@ -65,7 +64,7 @@ func GetNetworkName(ctx context.Context, sm *StateManager, st cid.Cid) (dtypes.N return ias.NetworkName() } -func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch, msgs []*types.Message, ts *types.TipSet) (cid.Cid, []*api.InvocResult, error) { +func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch, msgs []*types.Message, ts *types.TipSet) (cid.Cid, []*types.InvocResult, error) { if ts == nil { ts = sm.cs.GetHeaviestTipSet() } @@ -201,8 +200,8 @@ func CheckTotalFIL(ctx context.Context, cs *store.ChainStore, ts *types.TipSet) return sum, nil } -func MakeMsgGasCost(msg *types.Message, ret *vm.ApplyRet) api.MsgGasCost { - return api.MsgGasCost{ +func MakeMsgGasCost(msg *types.Message, ret *vm.ApplyRet) types.MsgGasCost { + return types.MsgGasCost{ Message: msg.Cid(), GasUsed: big.NewInt(ret.GasUsed), BaseFeeBurn: ret.GasCosts.BaseFeeBurn, diff --git a/chain/types/execresult.go b/chain/types/execresult.go index 98d06a390ab..e73329abb53 100644 --- a/chain/types/execresult.go +++ b/chain/types/execresult.go @@ -7,6 +7,10 @@ import ( "runtime" "strings" "time" + + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/go-state-types/abi" ) type ExecutionTrace struct { @@ -19,6 +23,16 @@ type ExecutionTrace struct { Subcalls []ExecutionTrace } +type InvocResult struct { + MsgCid cid.Cid + Msg *Message + MsgRct *MessageReceipt + GasCost MsgGasCost + ExecutionTrace ExecutionTrace + Error string + Duration time.Duration +} + type GasTrace struct { Name string @@ -36,6 +50,17 @@ type GasTrace struct { Callers []uintptr `json:"-"` } +type MsgGasCost struct { + Message cid.Cid // Can be different than requested, in case it was replaced, but only gas values changed + GasUsed abi.TokenAmount + BaseFeeBurn abi.TokenAmount + OverEstimationBurn abi.TokenAmount + MinerPenalty abi.TokenAmount + MinerTip abi.TokenAmount + Refund abi.TokenAmount + TotalCost abi.TokenAmount +} + type Loc struct { File string Line int diff --git a/cli/state.go b/cli/state.go index 021911f4468..5f2d1f1fa4c 100644 --- a/cli/state.go +++ b/cli/state.go @@ -508,7 +508,7 @@ var StateExecTraceCmd = &cli.Command{ return err } - var trace *api.InvocResult + var trace *types.InvocResult for _, t := range cso.Trace { if t.Msg.From == msg.From && t.Msg.Nonce == msg.Nonce { trace = t diff --git a/cmd/lotus-bench/import.go b/cmd/lotus-bench/import.go index 13824d07d62..28ce9633a2c 100644 --- a/cmd/lotus-bench/import.go +++ b/cmd/lotus-bench/import.go @@ -31,7 +31,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/blockstore" badgerbs "github.com/filecoin-project/lotus/blockstore/badger" "github.com/filecoin-project/lotus/chain/consensus/filcns" @@ -50,7 +49,7 @@ import ( type TipSetExec struct { TipSet types.TipSetKey - Trace []*api.InvocResult + Trace []*types.InvocResult Duration time.Duration } @@ -501,7 +500,7 @@ func walkExecutionTrace(et *types.ExecutionTrace) { } } -func stripCallers(trace []*api.InvocResult) { +func stripCallers(trace []*types.InvocResult) { for _, t := range trace { walkExecutionTrace(&t.ExecutionTrace) } @@ -509,7 +508,7 @@ func stripCallers(trace []*api.InvocResult) { type Invocation struct { TipSet types.TipSetKey - Invoc *api.InvocResult + Invoc *types.InvocResult } const GasPerNs = 10 diff --git a/markets/storageadapter/dealpublisher.go b/markets/storageadapter/dealpublisher.go index 6a274e593f4..3556c997c8a 100644 --- a/markets/storageadapter/dealpublisher.go +++ b/markets/storageadapter/dealpublisher.go @@ -35,7 +35,7 @@ type dealPublisherAPI interface { WalletHas(context.Context, address.Address) (bool, error) StateAccountKey(context.Context, address.Address, types.TipSetKey) (address.Address, error) StateLookupID(context.Context, address.Address, types.TipSetKey) (address.Address, error) - StateCall(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error) + StateCall(context.Context, *types.Message, types.TipSetKey) (*types.InvocResult, error) } // DealPublisher batches deal publishing so that many deals can be included in diff --git a/markets/storageadapter/dealpublisher_test.go b/markets/storageadapter/dealpublisher_test.go index 35169bf41b9..34a04c4cda8 100644 --- a/markets/storageadapter/dealpublisher_test.go +++ b/markets/storageadapter/dealpublisher_test.go @@ -397,7 +397,7 @@ func (d *dpAPI) StateLookupID(ctx context.Context, a address.Address, key types. panic("don't call me") } -func (d *dpAPI) StateCall(ctx context.Context, message *types.Message, key types.TipSetKey) (*api.InvocResult, error) { +func (d *dpAPI) StateCall(ctx context.Context, message *types.Message, key types.TipSetKey) (*types.InvocResult, error) { var p markettypes.PublishStorageDealsParams if err := p.UnmarshalCBOR(bytes.NewReader(message.Params)); err != nil { return nil, xerrors.Errorf("unmarshal market params: %w", err) @@ -407,7 +407,7 @@ func (d *dpAPI) StateCall(ctx context.Context, message *types.Message, key types if p.Deals[0].Proposal.PieceSize == 1 { exit = exitcode.ErrIllegalState } - return &api.InvocResult{MsgRct: &types.MessageReceipt{ExitCode: exit}}, nil + return &types.InvocResult{MsgRct: &types.MessageReceipt{ExitCode: exit}}, nil } func getClientActor(t *testing.T) address.Address { diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 2c9572dc40d..3dfd450046d 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -249,7 +249,7 @@ func (a *EthModule) EthGetCode(ctx context.Context, ethAddr api.EthAddress, blkO ts := a.Chain.GetHeaviestTipSet() // Try calling until we find a height with no migration. - var res *api.InvocResult + var res *types.InvocResult for { res, err = a.StateManager.Call(ctx, msg, ts) if err != stmgr.ErrExpensiveFork { @@ -339,7 +339,7 @@ func (a *EthModule) EthGetStorageAt(ctx context.Context, ethAddr api.EthAddress, ts := a.Chain.GetHeaviestTipSet() // Try calling until we find a height with no migration. - var res *api.InvocResult + var res *types.InvocResult for { res, err = a.StateManager.Call(ctx, msg, ts) if err != stmgr.ErrExpensiveFork { @@ -588,7 +588,7 @@ func (a *EthModule) ethCallToFilecoinMessage(ctx context.Context, tx api.EthCall }, nil } -func (a *EthModule) applyMessage(ctx context.Context, msg *types.Message) (res *api.InvocResult, err error) { +func (a *EthModule) applyMessage(ctx context.Context, msg *types.Message) (res *types.InvocResult, err error) { ts := a.Chain.GetHeaviestTipSet() // Try calling until we find a height with no migration. diff --git a/node/impl/full/gas.go b/node/impl/full/gas.go index 8cbe9ea1c74..b5cccec1230 100644 --- a/node/impl/full/gas.go +++ b/node/impl/full/gas.go @@ -276,7 +276,7 @@ func gasEstimateGasLimit( } // Try calling until we find a height with no migration. - var res *api.InvocResult + var res *types.InvocResult for { res, err = smgr.CallWithGas(ctx, &msg, priorMsgs, ts) if err != stmgr.ErrExpensiveFork { diff --git a/node/impl/full/state.go b/node/impl/full/state.go index b63f044a97b..d6402f46a8e 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -401,7 +401,7 @@ func (m *StateModule) StateMinerPower(ctx context.Context, addr address.Address, }, nil } -func (a *StateAPI) StateCall(ctx context.Context, msg *types.Message, tsk types.TipSetKey) (res *api.InvocResult, err error) { +func (a *StateAPI) StateCall(ctx context.Context, msg *types.Message, tsk types.TipSetKey) (res *types.InvocResult, err error) { ts, err := a.Chain.GetTipSetFromKey(ctx, tsk) if err != nil { return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) @@ -419,7 +419,7 @@ func (a *StateAPI) StateCall(ctx context.Context, msg *types.Message, tsk types. return res, err } -func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.InvocResult, error) { +func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*types.InvocResult, error) { msgToReplay := mc var ts *types.TipSet var err error @@ -460,7 +460,7 @@ func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid. errstr = r.ActorErr.Error() } - return &api.InvocResult{ + return &types.InvocResult{ MsgCid: msgToReplay, Msg: m, MsgRct: &r.MessageReceipt, diff --git a/paychmgr/manager.go b/paychmgr/manager.go index fda9b101f2c..becac568624 100644 --- a/paychmgr/manager.go +++ b/paychmgr/manager.go @@ -30,7 +30,7 @@ var errProofNotSupported = errors.New("payment channel proof parameter is not su type stateManagerAPI interface { ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error) - Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error) + Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.InvocResult, error) } // paychAPI defines the API methods needed by the payment channel manager diff --git a/paychmgr/mock_test.go b/paychmgr/mock_test.go index 739bae25a1e..e7b9307cee1 100644 --- a/paychmgr/mock_test.go +++ b/paychmgr/mock_test.go @@ -40,7 +40,7 @@ type mockStateManager struct { lk sync.Mutex accountState map[address.Address]address.Address paychState map[address.Address]mockPchState - response *api.InvocResult + response *types.InvocResult lastCall *types.Message } @@ -83,7 +83,7 @@ func (sm *mockStateManager) GetPaychState(ctx context.Context, addr address.Addr return info.actor, info.state, nil } -func (sm *mockStateManager) setCallResponse(response *api.InvocResult) { +func (sm *mockStateManager) setCallResponse(response *types.InvocResult) { sm.lk.Lock() defer sm.lk.Unlock() @@ -97,7 +97,7 @@ func (sm *mockStateManager) getLastCall() *types.Message { return sm.lastCall } -func (sm *mockStateManager) Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error) { +func (sm *mockStateManager) Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.InvocResult, error) { sm.lk.Lock() defer sm.lk.Unlock() diff --git a/paychmgr/paych_test.go b/paychmgr/paych_test.go index 7de58478462..7a0512b7e7e 100644 --- a/paychmgr/paych_test.go +++ b/paychmgr/paych_test.go @@ -19,7 +19,6 @@ import ( "github.com/filecoin-project/specs-actors/v2/actors/builtin" tutils "github.com/filecoin-project/specs-actors/v2/support/testing" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors/builtin/paych" paychmock "github.com/filecoin-project/lotus/chain/actors/builtin/paych/mock" "github.com/filecoin-project/lotus/chain/types" @@ -558,7 +557,7 @@ func TestBestSpendable(t *testing.T) { // Return success exit code from calls to check if voucher is spendable bsapi := newMockBestSpendableAPI(s.mgr) - s.mock.setCallResponse(&api.InvocResult{ + s.mock.setCallResponse(&types.InvocResult{ MsgRct: &types.MessageReceipt{ ExitCode: 0, }, @@ -621,7 +620,7 @@ func TestCheckSpendable(t *testing.T) { // Return success exit code from VM call, which indicates that voucher is // spendable - successResponse := &api.InvocResult{ + successResponse := &types.InvocResult{ MsgRct: &types.MessageReceipt{ ExitCode: 0, }, @@ -643,7 +642,7 @@ func TestCheckSpendable(t *testing.T) { require.Equal(t, secret, p.Secret) // Check that if VM call returns non-success exit code, spendable is false - s.mock.setCallResponse(&api.InvocResult{ + s.mock.setCallResponse(&types.InvocResult{ MsgRct: &types.MessageReceipt{ ExitCode: 1, }, From aba9c1cc349a3a58205b0639094bdb4eda081fe0 Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Wed, 14 Dec 2022 00:40:31 -0500 Subject: [PATCH 3/8] Move HeadChange to chain/store --- api/api_full.go | 9 ++---- api/api_gateway.go | 5 +-- api/mocks/mock_full.go | 9 +++--- api/proxy_gen.go | 33 ++++++++++---------- api/v0api/full.go | 5 +-- api/v0api/gateway.go | 3 +- api/v0api/proxy_gen.go | 23 +++++++------- api/v0api/v0mocks/mock_full.go | 9 +++--- build/openrpc/full.json.gz | Bin 31072 -> 31073 bytes build/openrpc/gateway.json.gz | Bin 4977 -> 4982 bytes build/openrpc/miner.json.gz | Bin 15754 -> 15753 bytes build/openrpc/worker.json.gz | Bin 5278 -> 5278 bytes chain/events/cache.go | 5 +-- chain/events/events.go | 5 +-- chain/events/events_test.go | 22 ++++++------- chain/events/observer.go | 5 ++- chain/store/store.go | 28 +++++++++-------- cmd/lotus-shed/balancer.go | 2 +- gateway/node.go | 9 +++--- itests/api_test.go | 3 +- node/health.go | 3 +- node/impl/full/chain.go | 10 +++--- storage/wdpost/wdpost_sched.go | 4 +-- tools/stats/headbuffer/head_buffer.go | 6 ++-- tools/stats/headbuffer/head_buffer_test.go | 34 ++++++++++----------- tools/stats/sync/sync.go | 2 +- 26 files changed, 123 insertions(+), 111 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index c2e8ba3b122..5398765e74e 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -30,6 +30,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors/builtin" lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/builtin/power" + "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/repo/imports" @@ -71,7 +72,7 @@ type FullNode interface { // ChainNotify returns channel with chain head updates. // First message is guaranteed to be of len == 1, and type == 'current'. - ChainNotify(context.Context) (<-chan []*HeadChange, error) //perm:read + ChainNotify(context.Context) (<-chan []*store.HeadChange, error) //perm:read // ChainHead returns the current head of the chain. ChainHead(context.Context) (*types.TipSet, error) //perm:read @@ -162,7 +163,7 @@ type FullNode interface { // tRR // ``` // Would return `[revert(tBA), apply(tAB), apply(tAA)]` - ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*HeadChange, error) //perm:read + ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*store.HeadChange, error) //perm:read // ChainExport returns a stream of bytes with CAR dump of chain data. // The exported chain data includes the header chain from the given tipset @@ -1206,10 +1207,6 @@ type CommPRet struct { Root cid.Cid Size abi.UnpaddedPieceSize } -type HeadChange struct { - Type string - Val *types.TipSet -} type MsigProposeResponse int diff --git a/api/api_gateway.go b/api/api_gateway.go index b95299493ef..8be4287c84b 100644 --- a/api/api_gateway.go +++ b/api/api_gateway.go @@ -12,6 +12,7 @@ import ( "github.com/filecoin-project/go-state-types/dline" apitypes "github.com/filecoin-project/lotus/api/types" + "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" ) @@ -37,11 +38,11 @@ type Gateway interface { ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error) ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) - ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*HeadChange, error) + ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*store.HeadChange, error) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetAfterHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) - ChainNotify(context.Context) (<-chan []*HeadChange, error) + ChainNotify(context.Context) (<-chan []*store.HeadChange, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error) ChainGetGenesis(context.Context) (*types.TipSet, error) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index f32a2079b11..61197ec6083 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -36,6 +36,7 @@ import ( api "github.com/filecoin-project/lotus/api" apitypes "github.com/filecoin-project/lotus/api/types" miner0 "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + store "github.com/filecoin-project/lotus/chain/store" types "github.com/filecoin-project/lotus/chain/types" alerting "github.com/filecoin-project/lotus/journal/alerting" dtypes "github.com/filecoin-project/lotus/node/modules/dtypes" @@ -274,10 +275,10 @@ func (mr *MockFullNodeMockRecorder) ChainGetParentReceipts(arg0, arg1 interface{ } // ChainGetPath mocks base method. -func (m *MockFullNode) ChainGetPath(arg0 context.Context, arg1, arg2 types.TipSetKey) ([]*api.HeadChange, error) { +func (m *MockFullNode) ChainGetPath(arg0 context.Context, arg1, arg2 types.TipSetKey) ([]*store.HeadChange, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChainGetPath", arg0, arg1, arg2) - ret0, _ := ret[0].([]*api.HeadChange) + ret0, _ := ret[0].([]*store.HeadChange) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -364,10 +365,10 @@ func (mr *MockFullNodeMockRecorder) ChainHead(arg0 interface{}) *gomock.Call { } // ChainNotify mocks base method. -func (m *MockFullNode) ChainNotify(arg0 context.Context) (<-chan []*api.HeadChange, error) { +func (m *MockFullNode) ChainNotify(arg0 context.Context) (<-chan []*store.HeadChange, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChainNotify", arg0) - ret0, _ := ret[0].(<-chan []*api.HeadChange) + ret0, _ := ret[0].(<-chan []*store.HeadChange) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/api/proxy_gen.go b/api/proxy_gen.go index f7d2b022e12..2c531064e7a 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -35,6 +35,7 @@ import ( apitypes "github.com/filecoin-project/lotus/api/types" "github.com/filecoin-project/lotus/chain/actors/builtin" lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/journal/alerting" _ "github.com/filecoin-project/lotus/lib/sigs/delegated" @@ -135,7 +136,7 @@ type FullNodeStruct struct { ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` - ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*HeadChange, error) `perm:"read"` + ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) `perm:"read"` ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `perm:"read"` @@ -147,7 +148,7 @@ type FullNodeStruct struct { ChainHead func(p0 context.Context) (*types.TipSet, error) `perm:"read"` - ChainNotify func(p0 context.Context) (<-chan []*HeadChange, error) `perm:"read"` + ChainNotify func(p0 context.Context) (<-chan []*store.HeadChange, error) `perm:"read"` ChainPrune func(p0 context.Context, p1 PruneOpts) error `perm:"admin"` @@ -579,7 +580,7 @@ type GatewayStruct struct { ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `` - ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*HeadChange, error) `` + ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) `` ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `` @@ -591,7 +592,7 @@ type GatewayStruct struct { ChainHead func(p0 context.Context) (*types.TipSet, error) `` - ChainNotify func(p0 context.Context) (<-chan []*HeadChange, error) `` + ChainNotify func(p0 context.Context) (<-chan []*store.HeadChange, error) `` ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` @@ -1382,15 +1383,15 @@ func (s *FullNodeStub) ChainGetParentReceipts(p0 context.Context, p1 cid.Cid) ([ return *new([]*types.MessageReceipt), ErrNotSupported } -func (s *FullNodeStruct) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*HeadChange, error) { +func (s *FullNodeStruct) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) { if s.Internal.ChainGetPath == nil { - return *new([]*HeadChange), ErrNotSupported + return *new([]*store.HeadChange), ErrNotSupported } return s.Internal.ChainGetPath(p0, p1, p2) } -func (s *FullNodeStub) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*HeadChange, error) { - return *new([]*HeadChange), ErrNotSupported +func (s *FullNodeStub) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) { + return *new([]*store.HeadChange), ErrNotSupported } func (s *FullNodeStruct) ChainGetTipSet(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) { @@ -1448,14 +1449,14 @@ func (s *FullNodeStub) ChainHead(p0 context.Context) (*types.TipSet, error) { return nil, ErrNotSupported } -func (s *FullNodeStruct) ChainNotify(p0 context.Context) (<-chan []*HeadChange, error) { +func (s *FullNodeStruct) ChainNotify(p0 context.Context) (<-chan []*store.HeadChange, error) { if s.Internal.ChainNotify == nil { return nil, ErrNotSupported } return s.Internal.ChainNotify(p0) } -func (s *FullNodeStub) ChainNotify(p0 context.Context) (<-chan []*HeadChange, error) { +func (s *FullNodeStub) ChainNotify(p0 context.Context) (<-chan []*store.HeadChange, error) { return nil, ErrNotSupported } @@ -3769,15 +3770,15 @@ func (s *GatewayStub) ChainGetParentReceipts(p0 context.Context, p1 cid.Cid) ([] return *new([]*types.MessageReceipt), ErrNotSupported } -func (s *GatewayStruct) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*HeadChange, error) { +func (s *GatewayStruct) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) { if s.Internal.ChainGetPath == nil { - return *new([]*HeadChange), ErrNotSupported + return *new([]*store.HeadChange), ErrNotSupported } return s.Internal.ChainGetPath(p0, p1, p2) } -func (s *GatewayStub) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*HeadChange, error) { - return *new([]*HeadChange), ErrNotSupported +func (s *GatewayStub) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) { + return *new([]*store.HeadChange), ErrNotSupported } func (s *GatewayStruct) ChainGetTipSet(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) { @@ -3835,14 +3836,14 @@ func (s *GatewayStub) ChainHead(p0 context.Context) (*types.TipSet, error) { return nil, ErrNotSupported } -func (s *GatewayStruct) ChainNotify(p0 context.Context) (<-chan []*HeadChange, error) { +func (s *GatewayStruct) ChainNotify(p0 context.Context) (<-chan []*store.HeadChange, error) { if s.Internal.ChainNotify == nil { return nil, ErrNotSupported } return s.Internal.ChainNotify(p0) } -func (s *GatewayStub) ChainNotify(p0 context.Context) (<-chan []*HeadChange, error) { +func (s *GatewayStub) ChainNotify(p0 context.Context) (<-chan []*store.HeadChange, error) { return nil, ErrNotSupported } diff --git a/api/v0api/full.go b/api/v0api/full.go index 6d4ca066281..e577e06d61d 100644 --- a/api/v0api/full.go +++ b/api/v0api/full.go @@ -24,6 +24,7 @@ import ( "github.com/filecoin-project/lotus/api" apitypes "github.com/filecoin-project/lotus/api/types" lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" marketevents "github.com/filecoin-project/lotus/markets/loggers" "github.com/filecoin-project/lotus/node/modules/dtypes" @@ -60,7 +61,7 @@ type FullNode interface { // ChainNotify returns channel with chain head updates. // First message is guaranteed to be of len == 1, and type == 'current'. - ChainNotify(context.Context) (<-chan []*api.HeadChange, error) //perm:read + ChainNotify(context.Context) (<-chan []*store.HeadChange, error) //perm:read // ChainHead returns the current head of the chain. ChainHead(context.Context) (*types.TipSet, error) //perm:read @@ -152,7 +153,7 @@ type FullNode interface { // tRR // ``` // Would return `[revert(tBA), apply(tAB), apply(tAA)]` - ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*api.HeadChange, error) //perm:read + ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*store.HeadChange, error) //perm:read // ChainExport returns a stream of bytes with CAR dump of chain data. // The exported chain data includes the header chain from the given tipset diff --git a/api/v0api/gateway.go b/api/v0api/gateway.go index bd55917c712..84efd3362dd 100644 --- a/api/v0api/gateway.go +++ b/api/v0api/gateway.go @@ -13,6 +13,7 @@ import ( abinetwork "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" ) @@ -41,7 +42,7 @@ type Gateway interface { ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) - ChainNotify(context.Context) (<-chan []*api.HeadChange, error) + ChainNotify(context.Context) (<-chan []*store.HeadChange, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) diff --git a/api/v0api/proxy_gen.go b/api/v0api/proxy_gen.go index 40eeadd215d..77e859aa07b 100644 --- a/api/v0api/proxy_gen.go +++ b/api/v0api/proxy_gen.go @@ -26,6 +26,7 @@ import ( "github.com/filecoin-project/lotus/api" apitypes "github.com/filecoin-project/lotus/api/types" lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" marketevents "github.com/filecoin-project/lotus/markets/loggers" "github.com/filecoin-project/lotus/node/modules/dtypes" @@ -62,7 +63,7 @@ type FullNodeStruct struct { ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` - ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*api.HeadChange, error) `perm:"read"` + ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) `perm:"read"` ChainGetRandomnessFromBeacon func(p0 context.Context, p1 types.TipSetKey, p2 crypto.DomainSeparationTag, p3 abi.ChainEpoch, p4 []byte) (abi.Randomness, error) `perm:"read"` @@ -76,7 +77,7 @@ type FullNodeStruct struct { ChainHead func(p0 context.Context) (*types.TipSet, error) `perm:"read"` - ChainNotify func(p0 context.Context) (<-chan []*api.HeadChange, error) `perm:"read"` + ChainNotify func(p0 context.Context) (<-chan []*store.HeadChange, error) `perm:"read"` ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` @@ -438,7 +439,7 @@ type GatewayStruct struct { ChainHead func(p0 context.Context) (*types.TipSet, error) `` - ChainNotify func(p0 context.Context) (<-chan []*api.HeadChange, error) `` + ChainNotify func(p0 context.Context) (<-chan []*store.HeadChange, error) `` ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` @@ -616,15 +617,15 @@ func (s *FullNodeStub) ChainGetParentReceipts(p0 context.Context, p1 cid.Cid) ([ return *new([]*types.MessageReceipt), ErrNotSupported } -func (s *FullNodeStruct) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*api.HeadChange, error) { +func (s *FullNodeStruct) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) { if s.Internal.ChainGetPath == nil { - return *new([]*api.HeadChange), ErrNotSupported + return *new([]*store.HeadChange), ErrNotSupported } return s.Internal.ChainGetPath(p0, p1, p2) } -func (s *FullNodeStub) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*api.HeadChange, error) { - return *new([]*api.HeadChange), ErrNotSupported +func (s *FullNodeStub) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) { + return *new([]*store.HeadChange), ErrNotSupported } func (s *FullNodeStruct) ChainGetRandomnessFromBeacon(p0 context.Context, p1 types.TipSetKey, p2 crypto.DomainSeparationTag, p3 abi.ChainEpoch, p4 []byte) (abi.Randomness, error) { @@ -693,14 +694,14 @@ func (s *FullNodeStub) ChainHead(p0 context.Context) (*types.TipSet, error) { return nil, ErrNotSupported } -func (s *FullNodeStruct) ChainNotify(p0 context.Context) (<-chan []*api.HeadChange, error) { +func (s *FullNodeStruct) ChainNotify(p0 context.Context) (<-chan []*store.HeadChange, error) { if s.Internal.ChainNotify == nil { return nil, ErrNotSupported } return s.Internal.ChainNotify(p0) } -func (s *FullNodeStub) ChainNotify(p0 context.Context) (<-chan []*api.HeadChange, error) { +func (s *FullNodeStub) ChainNotify(p0 context.Context) (<-chan []*store.HeadChange, error) { return nil, ErrNotSupported } @@ -2629,14 +2630,14 @@ func (s *GatewayStub) ChainHead(p0 context.Context) (*types.TipSet, error) { return nil, ErrNotSupported } -func (s *GatewayStruct) ChainNotify(p0 context.Context) (<-chan []*api.HeadChange, error) { +func (s *GatewayStruct) ChainNotify(p0 context.Context) (<-chan []*store.HeadChange, error) { if s.Internal.ChainNotify == nil { return nil, ErrNotSupported } return s.Internal.ChainNotify(p0) } -func (s *GatewayStub) ChainNotify(p0 context.Context) (<-chan []*api.HeadChange, error) { +func (s *GatewayStub) ChainNotify(p0 context.Context) (<-chan []*store.HeadChange, error) { return nil, ErrNotSupported } diff --git a/api/v0api/v0mocks/mock_full.go b/api/v0api/v0mocks/mock_full.go index 32280693bc2..5183e6418e5 100644 --- a/api/v0api/v0mocks/mock_full.go +++ b/api/v0api/v0mocks/mock_full.go @@ -37,6 +37,7 @@ import ( apitypes "github.com/filecoin-project/lotus/api/types" v0api "github.com/filecoin-project/lotus/api/v0api" miner0 "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + store "github.com/filecoin-project/lotus/chain/store" types "github.com/filecoin-project/lotus/chain/types" alerting "github.com/filecoin-project/lotus/journal/alerting" marketevents "github.com/filecoin-project/lotus/markets/loggers" @@ -262,10 +263,10 @@ func (mr *MockFullNodeMockRecorder) ChainGetParentReceipts(arg0, arg1 interface{ } // ChainGetPath mocks base method. -func (m *MockFullNode) ChainGetPath(arg0 context.Context, arg1, arg2 types.TipSetKey) ([]*api.HeadChange, error) { +func (m *MockFullNode) ChainGetPath(arg0 context.Context, arg1, arg2 types.TipSetKey) ([]*store.HeadChange, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChainGetPath", arg0, arg1, arg2) - ret0, _ := ret[0].([]*api.HeadChange) + ret0, _ := ret[0].([]*store.HeadChange) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -367,10 +368,10 @@ func (mr *MockFullNodeMockRecorder) ChainHead(arg0 interface{}) *gomock.Call { } // ChainNotify mocks base method. -func (m *MockFullNode) ChainNotify(arg0 context.Context) (<-chan []*api.HeadChange, error) { +func (m *MockFullNode) ChainNotify(arg0 context.Context) (<-chan []*store.HeadChange, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChainNotify", arg0) - ret0, _ := ret[0].(<-chan []*api.HeadChange) + ret0, _ := ret[0].(<-chan []*store.HeadChange) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 01c7a7aacb55dc13232be308df626e29222b38c3..30b054da07e72138e92cd5ec6413fedf223cf5b7 100644 GIT binary patch delta 27584 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 dWB-(TJTe*gdg|NrNnKo@86006(x?+pL| diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 3bc2366d547ce42c7fda923d7ef668dd939c29ea..06ee5f83b2371fb23bc5f1ef63055da1005b7dd3 100644 GIT binary patch delta 13926 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 ARR910 delta 13927 zcmV-tHkiqYdy0Fo5CQ_w*OL+gtpP!kzyfLk7PBh@X8{3}lamBG0ppX-1m}O4Xixl!iAnGIyf-l_LMVBb z#TpYf83`ML&#t?Fh3!kkenlH$76>o;{^feM!b}45ygNdND%c1i28D(~aX)pehS<=b zWCJCqa%+NUG}y|1DY5FRlBNxxb}tELW)IyZbI53Td$1U;iG$3q2lEFqTKsoB9GXKq z8nS=Lz<(ZK`{7~f+!@O|qzS3^G$$NobebW`OFvMW?Gpq|3lpRrjrh(FI!ugKQsgNy z(Sv+*d5dkEkKxO>*B2sFh+;4Lu|zraG+`6SfI4Xz@P?6x+$3tMO45C(Xp|HZkzhO( ztE#kvj95r-#+4LaWJOfN1QWhpxrj>Uy1&TP;usLK{I^WC02nn>K?B zI6-jaBKQw7R_yBmhPT6^>CW9Ho(vA)?CS`RCX;`$IbVNuhX2gn(QF0HiTNY=cAdg@AFW>!EYBp0@fsaU;>vn*}o>&B=`&p z@nC;Y;$oM%fX=}jF=NSfnXnc37ysh|6EX;1nFw0Ih8v4Q^R);$lp5QWa}V70%-y&Q zt$JXA2y!6fa3BGgTl!MZ+sNTv`5lNi*Mw0phX%GVgPi0bLk@5db1=GtmMgw|BLm58 znXJYC^r;xQbnO_(6(bWtjGQs$$gm4Ak%xa7{1bz6`6BEQ*}Iqqu)+)3-ZzB&-@x$# zd_>%xnBh5f0J=lYhEMK4YXoeJ3=tmLlLnCmzizI>c@N;O-JS&D0_Y$SK^a{fyb{|1 zhO7<86y8y6UX#<`0W=uC!)zmvM=UVBY=_=qve*Zw#AOJY9&`ab0{EH;3u=xXmjQn$ zL=H0J!Jc!+jsa$3HKRy7$U@M2>A}Y?Si5MxwnWq^bXH(( zOM}sX#u9<}vUBo5|E&4qB-Wlc^e762WP@BmH~~d0(JG(`Ym-F{bBHY$;CV>f97VYj zKrqlH$K*G34_yAo{xvyeU}jO{)&+lS!myQ`pgAVkT?*Rktj_OP9gTC6hI~1DhFvBI zq+Zs38jO+^S{9g-2CHt1Ru0k097C~ois0o3lw&fd&Pp;5oY6G{(6W5FcuVL#;mj^% zL};yo--)#W@D5^2Y#}KTd)sg)%K3Q(om<4*Pz$wgFwGU@ktHEO9W7!mFs7@)E739PM$*C#K%-_636h% z7dxKF5k4+HPtfxtE$|&8+?;DqrFYpN&zKF;$@NaIZ%M8nr4u(n(m2?Wc9bPNf|7+QbXOk|Tg@&$lmvleq&)Z5Gniso=~HgsNxn{X=!PUn%Q z0*fBs@cOz$7^h;IyItS+&A`)~Y>kjgrT3=|4vs)-frTT`+T-CkiYiPTMI-GhTS2mh zmbH=oD%1N){*q>v?ZxDGeDq!O(P2)azzKqudrXOoP2~JOpIexq3*UdWCtlWLs#37o z-jx}pR^bk(6mB-J$%UxGaw-GZN`W~(1*tjr9+tBVr^^VV_~%vMHStdLoT${SMe?Yz zUDAyLZI5uHP`6073FJGXeHxW-0VU4FFy{Gx=T|oCK z?%2YJFzv{%3oml^?zlA&eRc+C$dY(mGU!B7N8b}O{Nb(qxq}UKjvViWrbnP2Q%i(9 za}>l2i9q6U^qha)s}3LU_6)l0vu$$biF9v4cNzZl$9rr+ywZ;J#|Fg_B9mMt5!RdB zs<%m`=cFoxa9LE+G`;1m+DZKiQxU>cOe6J3vNDPpWLFhNl=PI6cQd)5YOir_Ey$UP zV=8&30*$6QNv)nxk|~wGiZG~3`veEqDO~yT!*V9mys&>9uFWKmV)LCvja#dc`c8q$ z)8z^U%d-I%D)l<$%5(AFl6KFlj~#vUWVJVLGAmWRplwXb$bVsseV7-n!>Rfbu`NX! zltIpO9&puE<}N6M-HH=IVE|jdo9Ss>S>2BHY;>R(MdPGtp&gfRG2C`pq}=b@m_ZWA zckJzIgjS;`N&vUTAj&}$4LBql{f; zMh6EuVR53IGIHJ$Lf6DVZ>`^t0)p-Zae{m30tXog-yySiO!R##6Z>wWbn#?#GPl5or;*r1C}RiOvoVf+U)y{PftV;xs8ysFa92uZ8`J0 zZ7P)th7-MRE?Y$9B4vn2oT)^uSbzLMjd*{r;6w2I^h9tMWlQ9US!qowz(oE!!PeXTn>J5-_ws* z56-8vyI=p0&1*-67hbd0`3{~+_D%JiXc#YKI>MYM7%m8P88+(e1_~kONkNZ*UxR;F zKV^JX6bo0_UAFWi*s2l+S2m!06Rj9GzeceOOf*|B7NQt(s`8+*b{uYF!~~@aMA@r_ z1MQ`|Ax3NBaCZes78hsHN@_?sjZ|(Ez7R$-CJP^g8{R}p%=Gh$cMNBNuXnM~@e&e( ztjhP_$D_~lLy2Vtc$QP_?*h5DxG{gGsIXr&Kwn~8C*JxUbnC^;pSoFN2;#wc1HPsx z=j|utx^R(Ixv;1G&aIMjlsSA6RlYz~*E9U67Bz@_Z_F#aDxcoe;+#a8Cu2NkbWt0z zGrGux=|#}jL0IL|uHWD)d*!y;Z(fSQ+EwGZh%s8Jy(4cvQ^*gXYh$U*v{8TQ8D0L= zq$X$o)IF9e%wzit^v@c(ESt}~mkNR`g`oFoX@$`OLP<;YP8@gQxD&^nIPS#plZ)f5 z+_Ud_2j0&Kw3nO2kBGf>ZyRj5C4lUtvY)&=m*k}v`Ypq%KlPng6r%Rj+~!~?#%(FAfX5nTpXwszFl z`+C2py??MVN5}hliT?SGYDYSkX?Q`PoU(7)m0+MjPZOn2jm1>?yRMiqu(Cw;=1k&5l z8yUk+D~s$#DjLEsYVdBud~NWVxQH`Zs2|SZW`zh7GjInjc^7^B*(os`1YNEzD$4H^ zaJ9?Zb9z^+J`o*rRr!Azo1U67?u7`5Nlt*Y_h6`|Hth=l9JFSd%>befZ95>axs(@PRC8rDEfK-)?s)HKFjJ=Crq zYF7`ntB2avL+yX+q3*UOKg>zP3w7ElF(_9VtU>XGTxfaPJ$^zfV5w{RL?4AZKc}Ob z`aeCoEm;CNXlGaj`7NK+Lh$Y(U)gNq-9sKT7P4MHgWVvXXPl|){+YUn`|btPa*R!X zHr|@%hcz+X$fNW1%);(6^29&uuN6xlna-Nudoq4B@D_jX9I~aH;ZKM`6EYY+Nf<;Q zpc@{_1?!vZoDoxTfn4O=ae*gh{Q}L!jCxxwIkUX03rYofx8Z2^EsMx1#K`ml-ix9U z-h;=U7F?VEfja3Ca&q=OT*5PeDJgdHB)n;-W|&04)t<~46Yx&SjIN1!{Pu!RLwy4? zMtN1Oshoe&XSs1gi!=o#gK>60rXabZ)tx=iQuQw+*e7dx6D(5|n1`+t@pXVa&>oQ`_IF zlyLU8x1~MS+~_{d71;{-XY6=YzERuz!i`0t89mANj=GU0L{Myp5#1Q41OKXp`DFzP zasovDP9)4Yi(qg{<}}!BcxPpN$0KY1G}v}tQ3kC`VUp>Aohl0o`BCn9`#>-IBsT6d zw19uc=G>u-8q^A6YwB))zO(eZhRA{`+B(0_=PqJZJojo?sKgf3U4m>QzDeY9C?vC@Py%^hX~iz! zeNC@M)98mlS14Jqp>$Vi-g1og3$r`>g@u22&Sl1VQ;RbSCfnAGwBT~8+^&p*EU+jO zaBEnP3Ea10Hzu%5&2;*`N;-!py+4yb6eE88adJcyD(s~hNHsD3>Szw8&4P2zMCK$RQ>A-vf;HQ-cnd@{i2;N zByy|-BzVYbk@}Ly{?scrs{1kiwu%o z#4>Gv#0hR|HlL_()`HzP${av~4YoLn;h=>h7!<<4A z!oG1oB6fUwl6i!$Lb*vGr4E0VS3lX}6Gk1h?|oE6(a8>4q3aB+JBQ1U=5Wa%#Iyj) zY@;NG65%RB6rE8+DNXUBQXIzmAScBkq-gn9LpGLwwZg>m zuPw50fNRIV9Ru$?0}p?5!ivu=WG;}jf9f%B1VA?9!WrK84Xi@mjX)~k+bFndtQ*HP zn{BVq$_CKJoaO*SF2iI|DV#EknWHFY9`Ht9su=rTX`a5W>pjh{iE&ubXb?21iQk9`F=rHgoT>jrf}Ukx*L!oxyyl{r07|=%yW^?PJ`@ z>P}X7vbvMiJ0z?7dQM80C%G_z7XFGZkZoZD%FBNvo5=1gcuye9v$}0bw&#qfll7gf z?__-^>vu`k_j9tn;*zYfpCu0H>7;v`ewNf2I(gp7^G=?3@_d)%`5-4pONy|Mh#&_t zPlWx7HXj_i5+(BMi}qZY+n4gWUAH6fi$>PT{!aFHvcHr4yCnOEIca@Tnth^o$dlp? zqRq+R7>GVmUjVrl8ZtxoOwgLOIP9O>}?SpqWmSKm_}>snG`8(rANDqjef>r!`uH zqtvd;cz4fL*sf&7cUrI0dMa9PQkdC(fnej*_5emD4L76Is;|j{KHJe>(IIqNtJ7LL zqqUyqy2ehIbh<=EmrM(D#4nJApo`?KEvQMZcmmS)Pk0g?wxv{(qv%e0I<>MBYNdaZ z>77jXWcp!YhI3ol74@?!a`x@NuUV7bL+i;Fc}W)CE}|3n&o1usc}S63ena<{(x~%p zg7^*H2XnX&I+(r!grvv_~+m;koKF2KZPkQivc@!jc(A*U8C{a&Ts!6!^Or%ChK z|BK7au-?@t=-eXaCMzL4rw3|BIc}1Zt?$k4+ZlE0U6LLJplT}>m_$)YWbI- zcScZW1hr=bbsGL`JUGb7llFM>0+S1f@YFOxDl#!hvQzH)a}49<#w2_Bxf4w@^hUfi_o=8E6(US_%OJ5-{Wc zu`FZ)N`NccME1R6yNiJBPy@LxpmQ)ooEz5?f(aM}P;56aYmI*;le3!70d>@2gli6O zGPGl-?i9JOpOaza5t=Eh*j&-KWYdHVqi~A&@H4TYX(HMB5`RUBP=FK2pa=pG4NefW zPRX3U2Crm4zt86`V#T^Lg-?MeD+;xe8!LO*)gEP;P(Ljwt3=O6U03BqiN9L_Q5-unXFW6Khf!a_tv7u zEm#wVEwG{vx+Z>azLb&QR&$t@iHX#rZ%tP8^}(pFxKKQ7_ii0&tnHhh7{^#d(GzpN zo>|yk9^)V}R{%H>M-L}RqDft7MPFZfR-HI&XV78qZEAlk#V7BH>Hm1_X}=<5hllEc z6t3X-@UcYDrP3AI6iz?W9`s>`m20BMh@MX1L|3D6(K9iGQEZQaGURCjXR<80sOnCM#>C4iKI+4s=6!e6*N20O z^2`5JX{`d!u<|;+kgee$Ct=VFWE1h0AFQ=o?`riFlim4+uakJhEUDA9WN=TMQHc+%DHd@h)MN5Tk%U1Y5|%B0$i+wb}E$ydIZalY4)N znJYMFMI8i81T7cL(47C^I+Q_&x&9$<$4tA;Op~0*V@V>PpmY0yI?YdB1RM9Uh+T6zRU_F57%-<#p>UZe~M&}#x#h(QxF2=;)3T;$v#^9{5tD(I!LSyr}; z>GvwfDiMBuYc3i-ueg!Pfp2amvaiY#C}5$On5dbow`I|Rz1!0I|@hex=a&*g;3cvhBi@!~V8jU4%>B#F9%u%GRJOXn&DQcr(Ln zj*(^Vzr*YU|3gWgM!P6br$vAL)YGkrv6Zk?49)aOL0rp5c+G9BON&OHTHTVyDq2?P z(qV7V>kF5A!Exb_tbzuGv9JNbG}J;KkYYt7{UB-PvxjQlk+7fER8@#~c^GR73F%RE z;{mB@&e{imV#@+^h(#0uBpX0QAZw%zSV9*V)UvQCyp0ly3phZyLi>N<5-~8Rj*Ow@ zG|2x;?~vnQ69E^_5!(P`iHuu!|C;;(Eo=f~2_0xK4rlHGIs$O-YY)8L`>O}^y~7^( zPY>*UziPJFhf_ZOu5^ui}Qs;1bGKn}W48#ig`jiaIf71HZ(gMadOycL&qvkfrO9Ih<}#QMvif8Rv_EP9Vz zwg>MZw&2V{2>?QzE>TQgUy~1VAHp1LNJEMe@HeLy-aksM?+X>6k{q|@xgQPMOmZqW zId@JU?5KPk6^3pFwLzQ4s>T78hpPtd)gxBpT_^^vruwNN9#el~E0T%{EVH6lgC^Ml ztTT?O7rh!ZeTD$m)YKKmux7Qc9me_`5vyH@>9fkIaba9qKwZtFOp~D62{cVY-Da$5 z#t4)oQhCH_D49xvPKAu>0#3Vt({je16h_8fAOqn>{wfbb-iGW#49+`jM+}zwr961; zIHf}5wqDpQIZ%Jqq%j5=hbXccBlY_VOPyT_`kZ>nmR?@2DCc|hO_RBoeSJ8Hrg4f3 zbG=+$GN<7Ux>wk^MeGlu*FBvtAB8Ep@hdO9M*PW1^v8w&BWNCW6nS`p#LT9i2USE9 z&#$n3iI|jJmk60LO!3#TH8rC^`Yg_yEmF)@FWrVStc3b_ofZ0%??=xJ9D zG*G%#L6OxH$YA`YV)^Vc_2d{D%K$4$K;A^ZC#Fp?VUl*DuLfDKyy`k9l%VMA$|YaL zl2$dsyv48cS!8MIeeNyxH%*xN{ErzX(Am5v1{H?Nkv4-anv5bwT?iwx29$P7`+4HJ*8KR|wBG1K)mr_tu3kk~ucE70@sjIRBx$wcoYbdpRnjh~?OP-= z<6DF6y5X{R5!JacwmGRGs<-ZK>}l^GZ0w~kDb{}h5!g#hSgrX5tj1-6JL(Z&G;u|# zGoKmT;gBe~-1%j+-sK|Vv3mL7_TobrvbOjmae7p%Zy_m%|yB%}>Sj;&r zOd1Vnv1tlG98h*x?N0_a_m8nc22>ncOZSCkqN&8F`O*BLx2QClKf=9F6wmL^clw_1 z@I?vBW}Z;QfgNKLIGpr3&a(J}HQ$qMX2QDgU_jG!kn187-~gI%y)sFJ{s4x{WAm!#E^hr?dgwQ9UZZm{FV+2ZKpge@$_Y{S!-UZQjLG(>odt8{s z=bqu(7xV_-mou?n|FVpc1vr02?)7Z->KyFjoXxfZ187-%qq+!OO3kaHq){(qv@)|e z%4~l2TX#!-2`@|vGsOg5oDy+t-lPms3{Kvj^UF=(N@1u8xA+}B3D-nMmA_FH929W^ z+0bFwSX?>K)qIsc$AmCU_B^G1Ih&%ZA%H^!+I zTFAUWa|Pb!Al1r?Mc~%qYY+FW6pPKqvZx4HyqQWG+Tm2!^~fz|rzgVdjNW86nvM@9 zdN0T?6TctJs)f~wq_2JjnrZ-j{a{#?l<@DFx2J`nOfFXr>qguyA=Iey?p?8aO6F97 z<7GFc7xs!ffot%2Fp7WT3OyeYlm29h4V?oB7Wgi>sTa&P;Pm7Nas=;aefW?VaxQ?Z za4~KuiS%AZT5nOltccv!{!J|XugiB!gZyiW{`cpfHJL@hp^rzy!A*ab!+>cItKj*#pkotF9+NBF|;0@;5SHsEL5gbXD!b)n1N zJC2<9EvM~9g6Q?0_SRtd&I`d8qm4)9dyn}1{)zBn$+RQwdadh2gJ4Vi!F!7)&J;8| zC75Aoom znf9vL9|`iQIstzHk7dNTzu;s~pQV(N{<_4_E-|!A4DAv_yTs7SiJ`R=db6?~*%oD0 z90Id-D;b!TycVc(^@$36@+1jqnMr>osdX=K$dTPomN?1UFZ|F2_s55Y89DByw=Zwv zmy#gz9nX=|ksC~yiVsSHEO9(1;MVd+1-R$Cp}b!JlR1A4@2qI&f{MftGF{T?HY&~( z-*0l%ALu0><`!7@g>lV9FU*v2rA;HPjRu?(0h3>jojS5Ut)C4#7oOel`DbE7(?sUG z4MV5IL=WNy3pm5Uo4^k50ej>*ie>!*x+2JRd%zw8Kc22M>NtvZJAucEd5B(p!7=9O zZME=V#vFeuGMThLyqKU!fRXN7U^0nZujpoyV0R`eDZbP42erM-_(E5A0pV}WY2VjJ z`fxgG!F8X$X(N+Sw>XkP8^ajo9H2y{irTdS!YjTzaRcEH$6ds6ixJ0N8pGLmGAK;- zbLDQkkv$xIL^{Rgcn1%6W9mCdV*kN8$pk%?frYQ@8 z)?(Q>jQV$`#^E$(&J{b@xw~fA z+W#OTg%k*1bki2u`#2ZtBpb4&>!+gdokxo|Ze>hMh0Q2`{rTd|^}|1WALwY%(>}om z52$~v^$y9UICb)9lK*DZ3ByW0I&^Jka@||YqW4!pWqSE@W22zk6GS$V2Q{t|7vLlA z<&=jzd0Y}jqRMx{G-SDx!#T-%8yRJl9{qW(@{M=Uk%|O}EU8jmNI@D^Iu4!a&$8Q( z2?IqwIEFSfFxzNHhdu4Bf6<=!_2Dw|TaSNU41XvlQ~dX{D;`uO+7Pf(WKe*lO6wTj zDj$fkRJ|Hsfqq=ImR(K62AX-Cmj&zTs5M)PW3HNqHc2RDmglQ4H*n3C`{&46VORPX z3J!3R;ENN2;()82;A9Ns$FNmX^Olv!lWL)om2~f5hPITGw5#kk$;(WY^z{z8jN5+} zMiXuefT$kxa4fiKAuQt1ci|o43?uE&AzNMv@7=2}H#t^yDZ2*v6<MyEsJ zqVptfvY8U!3wb@ zHG>MRb8Io>c$m+iD@#^|Htd_gwrsD2Y95Vk@33JjuCO>aYz_J0XgEGR7*2W5>>!@M#NQF3h@77zi`G%_Fp zs#TWk;sahXoge6Vc_SVTIMi-o^AJF3f9IgU8A0!DF-CMa<&MoCP-k`9gqO2T=)~mN z_@JMcC?qAq2TaW7VlsqM9@`t(>bd@uVfsMHcd^6|dAyj@DhEj+rmBA@Ny$#?oF~QR zN6kf(#<%EHDSnC+J7Yo**k$|ItHOxgq9ag_Le3GWhzT^5yhCcH8!`5y*6mXctFp(p^)kiZC;^4^6C zaK-0@GJ&f&zCvbrbX9+Lh86E6iClnN8gM2&a5|UC47P=?2@sfy!#!7=!39gz1BmZL z#j&5?g+Ymn<#`__CceYwnvbvNWk0M5rbN^mvn;u2yo2ECL;wwgu2xh8!VBO*-$4(N zMQc5Jy;GZIX<@srHcPX?zPrQCU2+l@>XzaI&5YKyk2T*x7v+B)bC#ZKo;z6fDhIyx z)643|g5mIX`}i{FC^DGftggCq$3_P6FfYkXGS)}L&Zu!)vk+<=Ms~%CBu9&;3Z|LmZ^(Zi^z<893b}&#@{p)kR8Dr^b_JUid^nW=$31O@N%$ivHNtt@8G|g6 z=2w($`hPB?37=%M9vqG zNtaaC1?s(^K)vr-%8!e)ZtGuz6@FiI0Z1s&ZlYV?6J&o_3Ie|5R;InP7OR`$I z7Nh{-oEt)lzfh5?N{S-aizluXNw~R=23xsEH0cE&9?};-EO~j&JQ7 za>Q*rhoyh@<4ZUWEk%}i!+ElplJ3Ci2RU&1eumM7o1Bdgro~x37s!+eD~&CRIHWvD z`co=APc2m^4!tEAnL_zVBF2BJ?k4IF4-X;KM|*?GV7xaP&H8&YXpZ(~rhYIRAI=5? zW3-*{yDoX-$vE|}IC4rEY$!a>+!_MOi+sUCAZXtmIPTn=CrwIvX4=z-Ko=@R991XiFatAp{VSiHR7CFb1 z5Y7N~ByJ2s?ac5Pl%^Z`Bue>)VZ2+0EXx&nP=uNYFv`aw-%xNbn!4cP{J6#XcU>O& z)APb8Cmvi9!@uaPUMP6@dH%8YdX3Hf&!2x2VH&}gMW#duzT^PBq>oA)tk{^gb`)NM zaptjj`8O)o37SvM!$UaOn@lI;y-|O9xHp~8;ojjK&Gq?IpCE)H*Q%8Tmg~9~!=@cf z^l5(v^}R`dX6}u~aJ)A&^ywa)>*IOf7);REjE7toK)izPEteJuT5s<3H=L)$HN1as zxczalCVxWA#0E@UkE|VO1AU6E8@F9iH3ahU*A(md{)p>Kn?0Q7VqZZ0%HEA&8f43oUBdA&>q7ply$YU zWRmDn;l(R4T&O~u2@duVG%{lRoPI@J5q=~NFMr`sQ&e|EK_$*6y)eH4Fv z(cs7P&!9gX9%wfSTx{wxt|;#@G3mYSU*WEM;_DMyQ9fw{T_6G<;txKafBwv{g}*|% z7Jbp?96HdlkcHh<#-oqtpM?T`2VIoa!!aes+HnwJ@+Q`P0+s1-I-TfoY=UPkA{6Z> ziPIo~Q(r$A9*p|a!6=4Sf6{-~C;h>}aMCJfVQ+dScEbdA!@;0G7>q{;13iwOKGY8m z2mNthA1NWYmyO{hg<&K^Jrl!G0>jB@G#HKb!_g>#VT|D0#Bee_=pT*_CSq+eFdXj= z159?10SW+0d>I@M55HEe%+s;YxLUX46{PF;WS#OQU3pjAci z{N$b#{yRqQNy)!c3Dj0I2?@+2k`}sJbpUlYD)fXP<=R`0F9}>Z3WN<)o(`u zw6u0D>;krjTnl@EZ6TLd0E5oy^P`*x1nB84I~&_N4;bhpy{{jRCgVwW9bCy>$Q)Yq5vQ0gYlt09Sx?5i5nh_hSS6GaCFf2 z$yWh--Dz(n2hYyXd{Vye6wRl^{Vvgbru=W>?ax3n$Nlt-3P2g7E&KbMpjP$7H*{;} zpx3f5v7!qn&m9|k{)G6orwW>rf7`mC74mPv+rLHfPg#HbJ4XIVrLbG%AJYo-4mrrS zumRV$2^s35fm&1!T{KV^4YV6dp^FB3PUOCiXrK&b&_xD4$xfk*4BFwqh%Pdyiwx=_ zgQSXZ&;k)x6w0|po9-atnRW_4VieF0rOmY6NUQh5Y@-jKxC89X@O1)bXuU( z0-YB4!L)zCnz-H_>Ye!SqKUd_qE7gC(L^sgn&|P-t1RqlM`UeTJ?%Y#Gb=0$?A12? zggqR*pYTEa{AjObB~!hp9gDxkpB&&ZT@&U(eJm-%U7TQL_s<%W% z3hgRhRTZh2n@@c0&}D+>6qh5$;u(aPU|7Ygys99P6e`uf5mHC#vntc0QVqV|leiG8 zKz2d~sMoObdj-1q}5t4#PDW zMhoZr&ObOe&&7N3UOg92K2JVREe(;p%uFfYvCUh*x7s?3bnCo@50ycRGKq@NM)5wj zrX(|9Y{*J2_VFIbINe{f6qQi@<5IZvcw9Z*v@Qc@{oA3LXX^A)u(C z1d+x=W~nH~;f6|)LOv%#v>Tptcb;aPV5E7Ko@D6ni|EywwTs}MkneZobZd$a0^5*9 z>z>u^Wwk(SIQ3ygVfgR?v$)j9kF{6GQe8WfV1F`e^09z)be+$zkp9kJ&8YBbT8a^E z=+pd_-1Tk|H^NM#Lv}@!|Ji%7{is*mSwo7hoFMs0-;_;u;Ij5BON0&zRxo!!h_d-a zOnbu+y3bB@Z^RAAyga-LX7LG&i!%k9KBQbKoVD?MPAz(n^0_?PZ^j%DN6v=4=++

qKA+8b3M<_kznL2!CcSOJ`g`9TedH| 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 delta 4190 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 diff --git a/chain/events/cache.go b/chain/events/cache.go index 2eba1f085b7..0ebab876f46 100644 --- a/chain/events/cache.go +++ b/chain/events/cache.go @@ -9,12 +9,13 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" ) type uncachedAPI interface { - ChainNotify(context.Context) (<-chan []*api.HeadChange, error) - ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*api.HeadChange, error) + ChainNotify(context.Context) (<-chan []*store.HeadChange, error) + ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*store.HeadChange, error) StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) // optional / for CalledMsg diff --git a/chain/events/events.go b/chain/events/events.go index 86aded64d45..92e1a21b4b4 100644 --- a/chain/events/events.go +++ b/chain/events/events.go @@ -11,6 +11,7 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" ) @@ -29,14 +30,14 @@ type TipSetObserver interface { } type EventAPI interface { - ChainNotify(context.Context) (<-chan []*api.HeadChange, error) + ChainNotify(context.Context) (<-chan []*store.HeadChange, error) ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) ChainGetTipSetAfterHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) ChainHead(context.Context) (*types.TipSet, error) StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error) - ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*api.HeadChange, error) + ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*store.HeadChange, error) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) // optional / for CalledMsg } diff --git a/chain/events/events_test.go b/chain/events/events_test.go index ad2dc8e7199..5684adcdaba 100644 --- a/chain/events/events_test.go +++ b/chain/events/events_test.go @@ -45,7 +45,7 @@ type fakeCS struct { mu sync.Mutex waitSub chan struct{} - subCh chan<- []*api.HeadChange + subCh chan<- []*store.HeadChange callNumber map[string]int } @@ -71,7 +71,7 @@ func (fcs *fakeCS) ChainHead(ctx context.Context) (*types.TipSet, error) { panic("implement me") } -func (fcs *fakeCS) ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*api.HeadChange, error) { +func (fcs *fakeCS) ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*store.HeadChange, error) { fcs.mu.Lock() fcs.callNumber["ChainGetPath"] = fcs.callNumber["ChainGetPath"] + 1 fcs.mu.Unlock() @@ -94,12 +94,12 @@ func (fcs *fakeCS) ChainGetPath(ctx context.Context, from, to types.TipSetKey) ( return nil, err } - path := make([]*api.HeadChange, len(revert)+len(apply)) + path := make([]*store.HeadChange, len(revert)+len(apply)) for i, r := range revert { - path[i] = &api.HeadChange{Type: store.HCRevert, Val: r} + path[i] = &store.HeadChange{Type: store.HCRevert, Val: r} } for j, i := 0, len(apply)-1; i >= 0; j, i = j+1, i-1 { - path[j+len(revert)] = &api.HeadChange{Type: store.HCApply, Val: apply[i]} + path[j+len(revert)] = &store.HeadChange{Type: store.HCApply, Val: apply[i]} } return path, nil } @@ -184,12 +184,12 @@ func (fcs *fakeCS) makeTs(t *testing.T, parents []cid.Cid, h abi.ChainEpoch, msg return ts } -func (fcs *fakeCS) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) { +func (fcs *fakeCS) ChainNotify(ctx context.Context) (<-chan []*store.HeadChange, error) { fcs.mu.Lock() defer fcs.mu.Unlock() fcs.callNumber["ChainNotify"] = fcs.callNumber["ChainNotify"] + 1 - out := make(chan []*api.HeadChange, 1) + out := make(chan []*store.HeadChange, 1) if fcs.subCh != nil { close(out) fcs.t.Error("already subscribed to notifications") @@ -201,7 +201,7 @@ func (fcs *fakeCS) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, e return nil, err } - out <- []*api.HeadChange{{Type: store.HCCurrent, Val: best}} + out <- []*store.HeadChange{{Type: store.HCCurrent, Val: best}} fcs.subCh = out close(fcs.waitSub) @@ -266,16 +266,16 @@ func (fcs *fakeCS) dropSub() { func (fcs *fakeCS) sub(rev, app []*types.TipSet) { <-fcs.waitSub - notif := make([]*api.HeadChange, len(rev)+len(app)) + notif := make([]*store.HeadChange, len(rev)+len(app)) for i, r := range rev { - notif[i] = &api.HeadChange{ + notif[i] = &store.HeadChange{ Type: store.HCRevert, Val: r, } } for i, r := range app { - notif[i+len(rev)] = &api.HeadChange{ + notif[i+len(rev)] = &store.HeadChange{ Type: store.HCApply, Val: r, } diff --git a/chain/events/observer.go b/chain/events/observer.go index 72b9deaee43..820b2fe9d4d 100644 --- a/chain/events/observer.go +++ b/chain/events/observer.go @@ -10,7 +10,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" @@ -81,7 +80,7 @@ func (o *observer) listenHeadChangesOnce(ctx context.Context) error { return xerrors.Errorf("listenHeadChanges ChainNotify call failed: %w", err) } - var cur []*api.HeadChange + var cur []*store.HeadChange var ok bool // Wait for first tipset or bail @@ -132,7 +131,7 @@ func (o *observer) listenHeadChangesOnce(ctx context.Context) error { return nil } -func (o *observer) applyChanges(ctx context.Context, changes []*api.HeadChange) error { +func (o *observer) applyChanges(ctx context.Context, changes []*store.HeadChange) error { // Used to wait for a prior notification round to finish (by tests) if len(changes) == 0 { return nil diff --git a/chain/store/store.go b/chain/store/store.go index 95f920fabf3..400e416a738 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -28,7 +28,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/pubsub" - "github.com/filecoin-project/lotus/api" bstore "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/adt" @@ -167,16 +166,16 @@ func NewChainStore(chainBs bstore.Blockstore, stateBs bstore.Blockstore, ds dsto cs.pubLk.Lock() defer cs.pubLk.Unlock() - notif := make([]*api.HeadChange, len(rev)+len(app)) + notif := make([]*HeadChange, len(rev)+len(app)) for i, r := range rev { - notif[i] = &api.HeadChange{ + notif[i] = &HeadChange{ Type: HCRevert, Val: r, } } for i, r := range app { - notif[i+len(rev)] = &api.HeadChange{ + notif[i+len(rev)] = &HeadChange{ Type: HCApply, Val: r, } @@ -283,14 +282,14 @@ const ( HCCurrent = "current" ) -func (cs *ChainStore) SubHeadChanges(ctx context.Context) chan []*api.HeadChange { +func (cs *ChainStore) SubHeadChanges(ctx context.Context) chan []*HeadChange { cs.pubLk.Lock() subch := cs.bestTips.Sub("headchange") head := cs.GetHeaviestTipSet() cs.pubLk.Unlock() - out := make(chan []*api.HeadChange, 16) - out <- []*api.HeadChange{{ + out := make(chan []*HeadChange, 16) + out <- []*HeadChange{{ Type: HCCurrent, Val: head, }} @@ -316,7 +315,7 @@ func (cs *ChainStore) SubHeadChanges(ctx context.Context) chan []*api.HeadChange return } select { - case out <- val.([]*api.HeadChange): + case out <- val.([]*HeadChange): default: log.Errorf("closing head change subscription due to slow reader") return @@ -1073,7 +1072,7 @@ func (cs *ChainStore) GetGenesis(ctx context.Context) (*types.BlockHeader, error // GetPath returns the sequence of atomic head change operations that // need to be applied in order to switch the head of the chain from the `from` // tipset to the `to` tipset. -func (cs *ChainStore) GetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*api.HeadChange, error) { +func (cs *ChainStore) GetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*HeadChange, error) { fts, err := cs.LoadTipSet(ctx, from) if err != nil { return nil, xerrors.Errorf("loading from tipset %s: %w", from, err) @@ -1087,12 +1086,12 @@ func (cs *ChainStore) GetPath(ctx context.Context, from types.TipSetKey, to type return nil, xerrors.Errorf("error getting tipset branches: %w", err) } - path := make([]*api.HeadChange, len(revert)+len(apply)) + path := make([]*HeadChange, len(revert)+len(apply)) for i, r := range revert { - path[i] = &api.HeadChange{Type: HCRevert, Val: r} + path[i] = &HeadChange{Type: HCRevert, Val: r} } for j, i := 0, len(apply)-1; i >= 0; j, i = j+1, i-1 { - path[j+len(revert)] = &api.HeadChange{Type: HCApply, Val: apply[i]} + path[j+len(revert)] = &HeadChange{Type: HCApply, Val: apply[i]} } return path, nil } @@ -1253,3 +1252,8 @@ func (cs *ChainStore) GetLatestBeaconEntry(ctx context.Context, ts *types.TipSet return nil, xerrors.Errorf("found NO beacon entries in the 20 latest tipsets") } + +type HeadChange struct { + Type string + Val *types.TipSet +} diff --git a/cmd/lotus-shed/balancer.go b/cmd/lotus-shed/balancer.go index edc484ab644..34d53896b6b 100644 --- a/cmd/lotus-shed/balancer.go +++ b/cmd/lotus-shed/balancer.go @@ -117,7 +117,7 @@ Supported roles: const confidence = 16 - var notifs <-chan []*lapi.HeadChange + var notifs <-chan []*store.HeadChange for { if notifs == nil { notifs, err = api.ChainNotify(ctx) diff --git a/gateway/node.go b/gateway/node.go index 13ac57c82f7..7e4972cb012 100644 --- a/gateway/node.go +++ b/gateway/node.go @@ -22,6 +22,7 @@ import ( apitypes "github.com/filecoin-project/lotus/api/types" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/lib/sigs" _ "github.com/filecoin-project/lotus/lib/sigs/bls" @@ -55,8 +56,8 @@ type TargetAPI interface { ChainGetTipSetAfterHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) ChainHasObj(context.Context, cid.Cid) (bool, error) ChainHead(ctx context.Context) (*types.TipSet, error) - ChainNotify(context.Context) (<-chan []*api.HeadChange, error) - ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*api.HeadChange, error) + ChainNotify(context.Context) (<-chan []*store.HeadChange, error) + ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*store.HeadChange, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error) ChainPutObj(context.Context, blocks.Block) error ChainGetGenesis(context.Context) (*types.TipSet, error) @@ -302,14 +303,14 @@ func (gw *Node) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, er return gw.target.ChainGetNode(ctx, p) } -func (gw *Node) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) { +func (gw *Node) ChainNotify(ctx context.Context) (<-chan []*store.HeadChange, error) { if err := gw.limit(ctx, chainRateLimitTokens); err != nil { return nil, err } return gw.target.ChainNotify(ctx) } -func (gw *Node) ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*api.HeadChange, error) { +func (gw *Node) ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*store.HeadChange, error) { if err := gw.limit(ctx, chainRateLimitTokens); err != nil { return nil, err } diff --git a/itests/api_test.go b/itests/api_test.go index ff303df3ec1..d9fe497aa76 100644 --- a/itests/api_test.go +++ b/itests/api_test.go @@ -18,6 +18,7 @@ import ( lapi "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/itests/kit" ) @@ -244,7 +245,7 @@ func (ts *apiSuite) testSlowNotify(t *testing.T) { full, miner, _ := kit.EnsembleMinimal(t, ts.opts...) // Subscribe a bunch of times to make sure we fill up any RPC buffers. - var newHeadsChans []<-chan []*lapi.HeadChange + var newHeadsChans []<-chan []*store.HeadChange for i := 0; i < 100; i++ { newHeads, err := full.ChainNotify(ctx) require.NoError(t, err) diff --git a/node/health.go b/node/health.go index 1be11921c0c..05b53d02bbd 100644 --- a/node/health.go +++ b/node/health.go @@ -10,6 +10,7 @@ import ( "github.com/libp2p/go-libp2p/core/network" lapi "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/store" ) var healthlog = logging.Logger("healthcheck") @@ -47,7 +48,7 @@ func NewLiveHandler(api lapi.FullNode) *HealthHandler { ) var ( countdown int32 - headCh <-chan []*lapi.HeadChange + headCh <-chan []*store.HeadChange backoff time.Duration = minbackoff err error ) diff --git a/node/impl/full/chain.go b/node/impl/full/chain.go index ca245dcdad3..f7c8ba00af1 100644 --- a/node/impl/full/chain.go +++ b/node/impl/full/chain.go @@ -41,7 +41,7 @@ import ( var log = logging.Logger("fullnode") type ChainModuleAPI interface { - ChainNotify(context.Context) (<-chan []*api.HeadChange, error) + ChainNotify(context.Context) (<-chan []*store.HeadChange, error) ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) ChainHasObj(context.Context, cid.Cid) (bool, error) ChainHead(context.Context) (*types.TipSet, error) @@ -50,7 +50,7 @@ type ChainModuleAPI interface { ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetAfterHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error) - ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*api.HeadChange, error) + ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*store.HeadChange, error) } var _ ChainModuleAPI = *new(api.FullNode) @@ -89,7 +89,7 @@ type ChainAPI struct { BaseBlockstore dtypes.BaseBlockstore } -func (m *ChainModule) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) { +func (m *ChainModule) ChainNotify(ctx context.Context) (<-chan []*store.HeadChange, error) { return m.Chain.SubHeadChanges(ctx), nil } @@ -105,7 +105,7 @@ func (m *ChainModule) ChainGetTipSet(ctx context.Context, key types.TipSetKey) ( return m.Chain.LoadTipSet(ctx, key) } -func (m *ChainModule) ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*api.HeadChange, error) { +func (m *ChainModule) ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*store.HeadChange, error) { return m.Chain.GetPath(ctx, from, to) } @@ -137,7 +137,7 @@ func (m *ChainModule) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) (* }, nil } -func (a *ChainAPI) ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*api.HeadChange, error) { +func (a *ChainAPI) ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*store.HeadChange, error) { return a.Chain.GetPath(ctx, from, to) } diff --git a/storage/wdpost/wdpost_sched.go b/storage/wdpost/wdpost_sched.go index 29c39ad9e44..32c5601b295 100644 --- a/storage/wdpost/wdpost_sched.go +++ b/storage/wdpost/wdpost_sched.go @@ -33,7 +33,7 @@ var log = logging.Logger("wdpost") type NodeAPI interface { ChainHead(context.Context) (*types.TipSet, error) - ChainNotify(context.Context) (<-chan []*api.HeadChange, error) + ChainNotify(context.Context) (<-chan []*store.HeadChange, error) StateMinerInfo(context.Context, address.Address, types.TipSetKey) (api.MinerInfo, error) StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) @@ -140,7 +140,7 @@ func (s *WindowPoStScheduler) Run(ctx context.Context) { s.ch.start() var ( - notifs <-chan []*api.HeadChange + notifs <-chan []*store.HeadChange err error gotCur bool ) diff --git a/tools/stats/headbuffer/head_buffer.go b/tools/stats/headbuffer/head_buffer.go index 5f668ab6e75..5857c6017b0 100644 --- a/tools/stats/headbuffer/head_buffer.go +++ b/tools/stats/headbuffer/head_buffer.go @@ -3,7 +3,7 @@ package headbuffer import ( "container/list" - "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/store" ) type HeadChangeStackBuffer struct { @@ -27,12 +27,12 @@ func NewHeadChangeStackBuffer(size int) *HeadChangeStackBuffer { // Push adds a HeadChange to stack buffer. If the length of // the stack buffer grows larger than the initizlized size, the // oldest HeadChange is returned. -func (h *HeadChangeStackBuffer) Push(hc *api.HeadChange) (rethc *api.HeadChange) { +func (h *HeadChangeStackBuffer) Push(hc *store.HeadChange) (rethc *store.HeadChange) { if h.buffer.Len() >= h.size { var ok bool el := h.buffer.Front() - rethc, ok = el.Value.(*api.HeadChange) + rethc, ok = el.Value.(*store.HeadChange) if !ok { // This shouldn't be possible, this method is typed and is the only place data // pushed to the buffer. diff --git a/tools/stats/headbuffer/head_buffer_test.go b/tools/stats/headbuffer/head_buffer_test.go index f9c0385c027..3b1d248cb1d 100644 --- a/tools/stats/headbuffer/head_buffer_test.go +++ b/tools/stats/headbuffer/head_buffer_test.go @@ -6,40 +6,40 @@ import ( "github.com/stretchr/testify/require" - "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/store" ) func TestHeadBuffer(t *testing.T) { //stm: @TOOLS_HEAD_BUFFER_PUSH_001, @TOOLS_HEAD_BUFFER_POP_001 t.Run("Straight Push through", func(t *testing.T) { hb := NewHeadChangeStackBuffer(5) - require.Nil(t, hb.Push(&api.HeadChange{Type: "1"})) - require.Nil(t, hb.Push(&api.HeadChange{Type: "2"})) - require.Nil(t, hb.Push(&api.HeadChange{Type: "3"})) - require.Nil(t, hb.Push(&api.HeadChange{Type: "4"})) - require.Nil(t, hb.Push(&api.HeadChange{Type: "5"})) + require.Nil(t, hb.Push(&store.HeadChange{Type: "1"})) + require.Nil(t, hb.Push(&store.HeadChange{Type: "2"})) + require.Nil(t, hb.Push(&store.HeadChange{Type: "3"})) + require.Nil(t, hb.Push(&store.HeadChange{Type: "4"})) + require.Nil(t, hb.Push(&store.HeadChange{Type: "5"})) - hc := hb.Push(&api.HeadChange{Type: "6"}) + hc := hb.Push(&store.HeadChange{Type: "6"}) require.Equal(t, hc.Type, "1") }) t.Run("Reverts", func(t *testing.T) { hb := NewHeadChangeStackBuffer(5) - require.Nil(t, hb.Push(&api.HeadChange{Type: "1"})) - require.Nil(t, hb.Push(&api.HeadChange{Type: "2"})) - require.Nil(t, hb.Push(&api.HeadChange{Type: "3"})) + require.Nil(t, hb.Push(&store.HeadChange{Type: "1"})) + require.Nil(t, hb.Push(&store.HeadChange{Type: "2"})) + require.Nil(t, hb.Push(&store.HeadChange{Type: "3"})) hb.Pop() - require.Nil(t, hb.Push(&api.HeadChange{Type: "3a"})) + require.Nil(t, hb.Push(&store.HeadChange{Type: "3a"})) hb.Pop() - require.Nil(t, hb.Push(&api.HeadChange{Type: "3b"})) - require.Nil(t, hb.Push(&api.HeadChange{Type: "4"})) - require.Nil(t, hb.Push(&api.HeadChange{Type: "5"})) + require.Nil(t, hb.Push(&store.HeadChange{Type: "3b"})) + require.Nil(t, hb.Push(&store.HeadChange{Type: "4"})) + require.Nil(t, hb.Push(&store.HeadChange{Type: "5"})) - hc := hb.Push(&api.HeadChange{Type: "6"}) + hc := hb.Push(&store.HeadChange{Type: "6"}) require.Equal(t, hc.Type, "1") - hc = hb.Push(&api.HeadChange{Type: "7"}) + hc = hb.Push(&store.HeadChange{Type: "7"}) require.Equal(t, hc.Type, "2") - hc = hb.Push(&api.HeadChange{Type: "8"}) + hc = hb.Push(&store.HeadChange{Type: "8"}) require.Equal(t, hc.Type, "3b") }) } diff --git a/tools/stats/sync/sync.go b/tools/stats/sync/sync.go index c8db1c543be..13b12432b26 100644 --- a/tools/stats/sync/sync.go +++ b/tools/stats/sync/sync.go @@ -85,7 +85,7 @@ func SyncWait(ctx context.Context, napi SyncWaitApi) error { } type BufferedTipsetChannelApi interface { - ChainNotify(context.Context) (<-chan []*api.HeadChange, error) + ChainNotify(context.Context) (<-chan []*store.HeadChange, error) Version(context.Context) (api.APIVersion, error) ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error) } From 69423c9230d8da4b62ec31904eea5279ba5fa213 Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Wed, 14 Dec 2022 00:49:28 -0500 Subject: [PATCH 4/8] Remove api dependency on stmgr --- api/api_full.go | 45 ++------- api/api_gateway.go | 4 +- api/api_storage.go | 4 +- api/docgen/docgen.go | 12 +-- api/mocks/mock_full.go | 24 ++--- api/proxy_gen.go | 88 +++++++++--------- api/v0api/full.go | 14 +-- api/v0api/gateway.go | 4 +- api/v0api/proxy_gen.go | 68 +++++++------- api/v0api/v0mocks/mock_full.go | 24 ++--- build/openrpc/full.json.gz | Bin 31073 -> 31090 bytes build/openrpc/gateway.json.gz | Bin 4982 -> 4989 bytes build/openrpc/miner.json.gz | Bin 15753 -> 15763 bytes build/openrpc/worker.json.gz | Bin 5278 -> 5278 bytes chain/gen/gen.go | 6 +- chain/market/fundmanager.go | 2 +- chain/market/fundmanager_test.go | 4 +- chain/stmgr/actors.go | 25 +++-- chain/stmgr/stmgr.go | 3 +- chain/stmgr/supply.go | 15 ++- chain/types/market_deal.go | 16 ++++ chain/types/mining_base_info.go | 18 ++++ chain/types/supply.go | 12 +++ cli/wallet_test.go | 4 +- cmd/tvx/simulate.go | 2 +- gateway/node.go | 20 ++-- gateway/node_test.go | 4 +- markets/retrievaladapter/provider_test.go | 21 ++--- .../ondealsectorcommitted_test.go | 13 ++- markets/utils/converters.go | 5 +- miner/miner.go | 6 +- node/impl/full/state.go | 32 +++---- node/impl/storminer.go | 8 +- storage/pipeline/currentdealinfo.go | 4 +- storage/pipeline/currentdealinfo_test.go | 32 +++---- storage/pipeline/mocks/api.go | 4 +- storage/pipeline/sealing.go | 2 +- storage/pipeline/states_failed_test.go | 4 +- 38 files changed, 279 insertions(+), 270 deletions(-) create mode 100644 chain/types/market_deal.go create mode 100644 chain/types/mining_base_info.go create mode 100644 chain/types/supply.go diff --git a/api/api_full.go b/api/api_full.go index 5398765e74e..b1dc2da0f23 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -19,7 +19,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/builtin/v8/paych" - "github.com/filecoin-project/go-state-types/builtin/v9/market" "github.com/filecoin-project/go-state-types/builtin/v9/miner" verifregtypes "github.com/filecoin-project/go-state-types/builtin/v9/verifreg" "github.com/filecoin-project/go-state-types/crypto" @@ -289,8 +288,8 @@ type FullNode interface { // MethodGroup: Miner - MinerGetBaseInfo(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*MiningBaseInfo, error) //perm:read - MinerCreateBlock(context.Context, *BlockTemplate) (*types.BlockMsg, error) //perm:write + MinerGetBaseInfo(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*types.MiningBaseInfo, error) //perm:read + MinerCreateBlock(context.Context, *BlockTemplate) (*types.BlockMsg, error) //perm:write // // UX ? @@ -523,13 +522,13 @@ type FullNode interface { // StateListActors returns the addresses of every actor in the state StateListActors(context.Context, types.TipSetKey) ([]address.Address, error) //perm:read // StateMarketBalance looks up the Escrow and Locked balances of the given address in the Storage Market - StateMarketBalance(context.Context, address.Address, types.TipSetKey) (MarketBalance, error) //perm:read + StateMarketBalance(context.Context, address.Address, types.TipSetKey) (types.MarketBalance, error) //perm:read // StateMarketParticipants returns the Escrow and Locked balances of every participant in the Storage Market - StateMarketParticipants(context.Context, types.TipSetKey) (map[string]MarketBalance, error) //perm:read + StateMarketParticipants(context.Context, types.TipSetKey) (map[string]types.MarketBalance, error) //perm:read // StateMarketDeals returns information about every deal in the Storage Market - StateMarketDeals(context.Context, types.TipSetKey) (map[string]*MarketDeal, error) //perm:read + StateMarketDeals(context.Context, types.TipSetKey) (map[string]*types.MarketDeal, error) //perm:read // StateMarketStorageDeal returns information about the indicated deal - StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*MarketDeal, error) //perm:read + StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*types.MarketDeal, error) //perm:read // StateGetAllocationForPendingDeal returns the allocation for a given deal ID of a pending deal. Returns nil if // pending allocation is not found. StateGetAllocationForPendingDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*verifregtypes.Allocation, error) //perm:read @@ -608,7 +607,7 @@ type FullNode interface { StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error) //perm:read // StateVMCirculatingSupplyInternal returns an approximation of the circulating supply of Filecoin at the given tipset. // This is the value reported by the runtime interface to actors code. - StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (CirculatingSupply, error) //perm:read + StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (types.CirculatingSupply, error) //perm:read // StateNetworkVersion returns the network version at the given tipset StateNetworkVersion(context.Context, types.TipSetKey) (apitypes.NetworkVersion, error) //perm:read // StateActorCodeCIDs returns the CIDs of all the builtin actors for the given network version @@ -1017,16 +1016,6 @@ func (o *QueryOffer) Order(client address.Address) RetrievalOrder { } } -type MarketBalance struct { - Escrow big.Int - Locked big.Int -} - -type MarketDeal struct { - Proposal market.DealProposal - State market.DealState -} - type RetrievalOrder struct { Root cid.Cid Piece *cid.Cid @@ -1160,26 +1149,6 @@ type DealCollateralBounds struct { Max abi.TokenAmount } -type CirculatingSupply struct { - FilVested abi.TokenAmount - FilMined abi.TokenAmount - FilBurnt abi.TokenAmount - FilLocked abi.TokenAmount - FilCirculating abi.TokenAmount - FilReserveDisbursed abi.TokenAmount -} - -type MiningBaseInfo struct { - MinerPower types.BigInt - NetworkPower types.BigInt - Sectors []builtin.ExtendedSectorInfo - WorkerKey address.Address - SectorSize abi.SectorSize - PrevBeaconEntry types.BeaconEntry - BeaconEntries []types.BeaconEntry - EligibleForMining bool -} - type BlockTemplate struct { Miner address.Address Parents types.TipSetKey diff --git a/api/api_gateway.go b/api/api_gateway.go index 8be4287c84b..4a6d78c87d8 100644 --- a/api/api_gateway.go +++ b/api/api_gateway.go @@ -57,8 +57,8 @@ type Gateway interface { StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*ActorState, error) //perm:read StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) - StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (MarketBalance, error) - StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*MarketDeal, error) + StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.MarketBalance, error) + StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*types.MarketDeal, error) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (MinerInfo, error) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error) diff --git a/api/api_storage.go b/api/api_storage.go index 05120678741..c093d15b8ad 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -213,7 +213,7 @@ type StorageMiner interface { StorageRedeclareLocal(ctx context.Context, id *storiface.ID, dropMissing bool) error //perm:admin MarketImportDealData(ctx context.Context, propcid cid.Cid, path string) error //perm:write - MarketListDeals(ctx context.Context) ([]*MarketDeal, error) //perm:read + MarketListDeals(ctx context.Context) ([]*types.MarketDeal, error) //perm:read MarketListRetrievalDeals(ctx context.Context) ([]retrievalmarket.ProviderDealState, error) //perm:read MarketGetDealUpdates(ctx context.Context) (<-chan storagemarket.MinerDeal, error) //perm:read MarketListIncompleteDeals(ctx context.Context) ([]storagemarket.MinerDeal, error) //perm:read @@ -293,7 +293,7 @@ type StorageMiner interface { RuntimeSubsystems(ctx context.Context) (MinerSubsystems, error) //perm:read DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error //perm:admin - DealsList(ctx context.Context) ([]*MarketDeal, error) //perm:admin + DealsList(ctx context.Context) ([]*types.MarketDeal, error) //perm:admin DealsConsiderOnlineStorageDeals(context.Context) (bool, error) //perm:admin DealsSetConsiderOnlineStorageDeals(context.Context, bool) error //perm:admin DealsConsiderOnlineRetrievalDeals(context.Context) (bool, error) //perm:admin diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index 3ef5c879c1c..55d7774390b 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -158,15 +158,15 @@ func init() { addExample(map[string]types.Actor{ "t01236": ExampleValue("init", reflect.TypeOf(types.Actor{}), nil).(types.Actor), }) - addExample(map[string]api.MarketDeal{ - "t026363": ExampleValue("init", reflect.TypeOf(api.MarketDeal{}), nil).(api.MarketDeal), + addExample(map[string]types.MarketDeal{ + "t026363": ExampleValue("init", reflect.TypeOf(types.MarketDeal{}), nil).(types.MarketDeal), }) - addExample(map[string]*api.MarketDeal{ - "t026363": ExampleValue("init", reflect.TypeOf(&api.MarketDeal{}), nil).(*api.MarketDeal), + addExample(map[string]*types.MarketDeal{ + "t026363": ExampleValue("init", reflect.TypeOf(&types.MarketDeal{}), nil).(*types.MarketDeal), }) - addExample(map[string]api.MarketBalance{ - "t026363": ExampleValue("init", reflect.TypeOf(api.MarketBalance{}), nil).(api.MarketBalance), + addExample(map[string]types.MarketBalance{ + "t026363": ExampleValue("init", reflect.TypeOf(types.MarketBalance{}), nil).(types.MarketBalance), }) addExample(map[string]*pubsub.TopicScoreSnapshot{ "/blocks": { diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 61197ec6083..7119ce4ec0b 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -1461,10 +1461,10 @@ func (mr *MockFullNodeMockRecorder) MinerCreateBlock(arg0, arg1 interface{}) *go } // MinerGetBaseInfo mocks base method. -func (m *MockFullNode) MinerGetBaseInfo(arg0 context.Context, arg1 address.Address, arg2 abi.ChainEpoch, arg3 types.TipSetKey) (*api.MiningBaseInfo, error) { +func (m *MockFullNode) MinerGetBaseInfo(arg0 context.Context, arg1 address.Address, arg2 abi.ChainEpoch, arg3 types.TipSetKey) (*types.MiningBaseInfo, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "MinerGetBaseInfo", arg0, arg1, arg2, arg3) - ret0, _ := ret[0].(*api.MiningBaseInfo) + ret0, _ := ret[0].(*types.MiningBaseInfo) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -3085,10 +3085,10 @@ func (mr *MockFullNodeMockRecorder) StateLookupRobustAddress(arg0, arg1, arg2 in } // StateMarketBalance mocks base method. -func (m *MockFullNode) StateMarketBalance(arg0 context.Context, arg1 address.Address, arg2 types.TipSetKey) (api.MarketBalance, error) { +func (m *MockFullNode) StateMarketBalance(arg0 context.Context, arg1 address.Address, arg2 types.TipSetKey) (types.MarketBalance, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateMarketBalance", arg0, arg1, arg2) - ret0, _ := ret[0].(api.MarketBalance) + ret0, _ := ret[0].(types.MarketBalance) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -3100,10 +3100,10 @@ func (mr *MockFullNodeMockRecorder) StateMarketBalance(arg0, arg1, arg2 interfac } // StateMarketDeals mocks base method. -func (m *MockFullNode) StateMarketDeals(arg0 context.Context, arg1 types.TipSetKey) (map[string]*api.MarketDeal, error) { +func (m *MockFullNode) StateMarketDeals(arg0 context.Context, arg1 types.TipSetKey) (map[string]*types.MarketDeal, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateMarketDeals", arg0, arg1) - ret0, _ := ret[0].(map[string]*api.MarketDeal) + ret0, _ := ret[0].(map[string]*types.MarketDeal) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -3115,10 +3115,10 @@ func (mr *MockFullNodeMockRecorder) StateMarketDeals(arg0, arg1 interface{}) *go } // StateMarketParticipants mocks base method. -func (m *MockFullNode) StateMarketParticipants(arg0 context.Context, arg1 types.TipSetKey) (map[string]api.MarketBalance, error) { +func (m *MockFullNode) StateMarketParticipants(arg0 context.Context, arg1 types.TipSetKey) (map[string]types.MarketBalance, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateMarketParticipants", arg0, arg1) - ret0, _ := ret[0].(map[string]api.MarketBalance) + ret0, _ := ret[0].(map[string]types.MarketBalance) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -3130,10 +3130,10 @@ func (mr *MockFullNodeMockRecorder) StateMarketParticipants(arg0, arg1 interface } // StateMarketStorageDeal mocks base method. -func (m *MockFullNode) StateMarketStorageDeal(arg0 context.Context, arg1 abi.DealID, arg2 types.TipSetKey) (*api.MarketDeal, error) { +func (m *MockFullNode) StateMarketStorageDeal(arg0 context.Context, arg1 abi.DealID, arg2 types.TipSetKey) (*types.MarketDeal, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateMarketStorageDeal", arg0, arg1, arg2) - ret0, _ := ret[0].(*api.MarketDeal) + ret0, _ := ret[0].(*types.MarketDeal) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -3505,10 +3505,10 @@ func (mr *MockFullNodeMockRecorder) StateSectorPreCommitInfo(arg0, arg1, arg2, a } // StateVMCirculatingSupplyInternal mocks base method. -func (m *MockFullNode) StateVMCirculatingSupplyInternal(arg0 context.Context, arg1 types.TipSetKey) (api.CirculatingSupply, error) { +func (m *MockFullNode) StateVMCirculatingSupplyInternal(arg0 context.Context, arg1 types.TipSetKey) (types.CirculatingSupply, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateVMCirculatingSupplyInternal", arg0, arg1) - ret0, _ := ret[0].(api.CirculatingSupply) + ret0, _ := ret[0].(types.CirculatingSupply) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 2c531064e7a..ad31757234e 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -284,7 +284,7 @@ type FullNodeStruct struct { MinerCreateBlock func(p0 context.Context, p1 *BlockTemplate) (*types.BlockMsg, error) `perm:"write"` - MinerGetBaseInfo func(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*MiningBaseInfo, error) `perm:"read"` + MinerGetBaseInfo func(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*types.MiningBaseInfo, error) `perm:"read"` MpoolBatchPush func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` @@ -450,13 +450,13 @@ type FullNodeStruct struct { StateLookupRobustAddress func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` - StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) `perm:"read"` + StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.MarketBalance, error) `perm:"read"` - StateMarketDeals func(p0 context.Context, p1 types.TipSetKey) (map[string]*MarketDeal, error) `perm:"read"` + StateMarketDeals func(p0 context.Context, p1 types.TipSetKey) (map[string]*types.MarketDeal, error) `perm:"read"` - StateMarketParticipants func(p0 context.Context, p1 types.TipSetKey) (map[string]MarketBalance, error) `perm:"read"` + StateMarketParticipants func(p0 context.Context, p1 types.TipSetKey) (map[string]types.MarketBalance, error) `perm:"read"` - StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*MarketDeal, error) `perm:"read"` + StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*types.MarketDeal, error) `perm:"read"` StateMinerActiveSectors func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` @@ -506,7 +506,7 @@ type FullNodeStruct struct { StateSectorPreCommitInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorPreCommitOnChainInfo, error) `perm:"read"` - StateVMCirculatingSupplyInternal func(p0 context.Context, p1 types.TipSetKey) (CirculatingSupply, error) `perm:"read"` + StateVMCirculatingSupplyInternal func(p0 context.Context, p1 types.TipSetKey) (types.CirculatingSupply, error) `perm:"read"` StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` @@ -622,9 +622,9 @@ type GatewayStruct struct { StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` - StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) `` + StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.MarketBalance, error) `` - StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*MarketDeal, error) `` + StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*types.MarketDeal, error) `` StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerInfo, error) `` @@ -771,7 +771,7 @@ type StorageMinerStruct struct { DealsImportData func(p0 context.Context, p1 cid.Cid, p2 string) error `perm:"admin"` - DealsList func(p0 context.Context) ([]*MarketDeal, error) `perm:"admin"` + DealsList func(p0 context.Context) ([]*types.MarketDeal, error) `perm:"admin"` DealsPieceCidBlocklist func(p0 context.Context) ([]cid.Cid, error) `perm:"admin"` @@ -809,7 +809,7 @@ type StorageMinerStruct struct { MarketListDataTransfers func(p0 context.Context) ([]DataTransferChannel, error) `perm:"write"` - MarketListDeals func(p0 context.Context) ([]*MarketDeal, error) `perm:"read"` + MarketListDeals func(p0 context.Context) ([]*types.MarketDeal, error) `perm:"read"` MarketListIncompleteDeals func(p0 context.Context) ([]storagemarket.MinerDeal, error) `perm:"read"` @@ -2197,14 +2197,14 @@ func (s *FullNodeStub) MinerCreateBlock(p0 context.Context, p1 *BlockTemplate) ( return nil, ErrNotSupported } -func (s *FullNodeStruct) MinerGetBaseInfo(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*MiningBaseInfo, error) { +func (s *FullNodeStruct) MinerGetBaseInfo(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*types.MiningBaseInfo, error) { if s.Internal.MinerGetBaseInfo == nil { return nil, ErrNotSupported } return s.Internal.MinerGetBaseInfo(p0, p1, p2, p3) } -func (s *FullNodeStub) MinerGetBaseInfo(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*MiningBaseInfo, error) { +func (s *FullNodeStub) MinerGetBaseInfo(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*types.MiningBaseInfo, error) { return nil, ErrNotSupported } @@ -3110,47 +3110,47 @@ func (s *FullNodeStub) StateLookupRobustAddress(p0 context.Context, p1 address.A return *new(address.Address), ErrNotSupported } -func (s *FullNodeStruct) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) { +func (s *FullNodeStruct) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.MarketBalance, error) { if s.Internal.StateMarketBalance == nil { - return *new(MarketBalance), ErrNotSupported + return *new(types.MarketBalance), ErrNotSupported } return s.Internal.StateMarketBalance(p0, p1, p2) } -func (s *FullNodeStub) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) { - return *new(MarketBalance), ErrNotSupported +func (s *FullNodeStub) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.MarketBalance, error) { + return *new(types.MarketBalance), ErrNotSupported } -func (s *FullNodeStruct) StateMarketDeals(p0 context.Context, p1 types.TipSetKey) (map[string]*MarketDeal, error) { +func (s *FullNodeStruct) StateMarketDeals(p0 context.Context, p1 types.TipSetKey) (map[string]*types.MarketDeal, error) { if s.Internal.StateMarketDeals == nil { - return *new(map[string]*MarketDeal), ErrNotSupported + return *new(map[string]*types.MarketDeal), ErrNotSupported } return s.Internal.StateMarketDeals(p0, p1) } -func (s *FullNodeStub) StateMarketDeals(p0 context.Context, p1 types.TipSetKey) (map[string]*MarketDeal, error) { - return *new(map[string]*MarketDeal), ErrNotSupported +func (s *FullNodeStub) StateMarketDeals(p0 context.Context, p1 types.TipSetKey) (map[string]*types.MarketDeal, error) { + return *new(map[string]*types.MarketDeal), ErrNotSupported } -func (s *FullNodeStruct) StateMarketParticipants(p0 context.Context, p1 types.TipSetKey) (map[string]MarketBalance, error) { +func (s *FullNodeStruct) StateMarketParticipants(p0 context.Context, p1 types.TipSetKey) (map[string]types.MarketBalance, error) { if s.Internal.StateMarketParticipants == nil { - return *new(map[string]MarketBalance), ErrNotSupported + return *new(map[string]types.MarketBalance), ErrNotSupported } return s.Internal.StateMarketParticipants(p0, p1) } -func (s *FullNodeStub) StateMarketParticipants(p0 context.Context, p1 types.TipSetKey) (map[string]MarketBalance, error) { - return *new(map[string]MarketBalance), ErrNotSupported +func (s *FullNodeStub) StateMarketParticipants(p0 context.Context, p1 types.TipSetKey) (map[string]types.MarketBalance, error) { + return *new(map[string]types.MarketBalance), ErrNotSupported } -func (s *FullNodeStruct) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*MarketDeal, error) { +func (s *FullNodeStruct) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*types.MarketDeal, error) { if s.Internal.StateMarketStorageDeal == nil { return nil, ErrNotSupported } return s.Internal.StateMarketStorageDeal(p0, p1, p2) } -func (s *FullNodeStub) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*MarketDeal, error) { +func (s *FullNodeStub) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*types.MarketDeal, error) { return nil, ErrNotSupported } @@ -3418,15 +3418,15 @@ func (s *FullNodeStub) StateSectorPreCommitInfo(p0 context.Context, p1 address.A return nil, ErrNotSupported } -func (s *FullNodeStruct) StateVMCirculatingSupplyInternal(p0 context.Context, p1 types.TipSetKey) (CirculatingSupply, error) { +func (s *FullNodeStruct) StateVMCirculatingSupplyInternal(p0 context.Context, p1 types.TipSetKey) (types.CirculatingSupply, error) { if s.Internal.StateVMCirculatingSupplyInternal == nil { - return *new(CirculatingSupply), ErrNotSupported + return *new(types.CirculatingSupply), ErrNotSupported } return s.Internal.StateVMCirculatingSupplyInternal(p0, p1) } -func (s *FullNodeStub) StateVMCirculatingSupplyInternal(p0 context.Context, p1 types.TipSetKey) (CirculatingSupply, error) { - return *new(CirculatingSupply), ErrNotSupported +func (s *FullNodeStub) StateVMCirculatingSupplyInternal(p0 context.Context, p1 types.TipSetKey) (types.CirculatingSupply, error) { + return *new(types.CirculatingSupply), ErrNotSupported } func (s *FullNodeStruct) StateVerifiedClientStatus(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) { @@ -4001,25 +4001,25 @@ func (s *GatewayStub) StateLookupID(p0 context.Context, p1 address.Address, p2 t return *new(address.Address), ErrNotSupported } -func (s *GatewayStruct) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) { +func (s *GatewayStruct) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.MarketBalance, error) { if s.Internal.StateMarketBalance == nil { - return *new(MarketBalance), ErrNotSupported + return *new(types.MarketBalance), ErrNotSupported } return s.Internal.StateMarketBalance(p0, p1, p2) } -func (s *GatewayStub) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) { - return *new(MarketBalance), ErrNotSupported +func (s *GatewayStub) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.MarketBalance, error) { + return *new(types.MarketBalance), ErrNotSupported } -func (s *GatewayStruct) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*MarketDeal, error) { +func (s *GatewayStruct) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*types.MarketDeal, error) { if s.Internal.StateMarketStorageDeal == nil { return nil, ErrNotSupported } return s.Internal.StateMarketStorageDeal(p0, p1, p2) } -func (s *GatewayStub) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*MarketDeal, error) { +func (s *GatewayStub) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*types.MarketDeal, error) { return nil, ErrNotSupported } @@ -4683,15 +4683,15 @@ func (s *StorageMinerStub) DealsImportData(p0 context.Context, p1 cid.Cid, p2 st return ErrNotSupported } -func (s *StorageMinerStruct) DealsList(p0 context.Context) ([]*MarketDeal, error) { +func (s *StorageMinerStruct) DealsList(p0 context.Context) ([]*types.MarketDeal, error) { if s.Internal.DealsList == nil { - return *new([]*MarketDeal), ErrNotSupported + return *new([]*types.MarketDeal), ErrNotSupported } return s.Internal.DealsList(p0) } -func (s *StorageMinerStub) DealsList(p0 context.Context) ([]*MarketDeal, error) { - return *new([]*MarketDeal), ErrNotSupported +func (s *StorageMinerStub) DealsList(p0 context.Context) ([]*types.MarketDeal, error) { + return *new([]*types.MarketDeal), ErrNotSupported } func (s *StorageMinerStruct) DealsPieceCidBlocklist(p0 context.Context) ([]cid.Cid, error) { @@ -4892,15 +4892,15 @@ func (s *StorageMinerStub) MarketListDataTransfers(p0 context.Context) ([]DataTr return *new([]DataTransferChannel), ErrNotSupported } -func (s *StorageMinerStruct) MarketListDeals(p0 context.Context) ([]*MarketDeal, error) { +func (s *StorageMinerStruct) MarketListDeals(p0 context.Context) ([]*types.MarketDeal, error) { if s.Internal.MarketListDeals == nil { - return *new([]*MarketDeal), ErrNotSupported + return *new([]*types.MarketDeal), ErrNotSupported } return s.Internal.MarketListDeals(p0) } -func (s *StorageMinerStub) MarketListDeals(p0 context.Context) ([]*MarketDeal, error) { - return *new([]*MarketDeal), ErrNotSupported +func (s *StorageMinerStub) MarketListDeals(p0 context.Context) ([]*types.MarketDeal, error) { + return *new([]*types.MarketDeal), ErrNotSupported } func (s *StorageMinerStruct) MarketListIncompleteDeals(p0 context.Context) ([]storagemarket.MinerDeal, error) { diff --git a/api/v0api/full.go b/api/v0api/full.go index e577e06d61d..f2a0961d209 100644 --- a/api/v0api/full.go +++ b/api/v0api/full.go @@ -269,8 +269,8 @@ type FullNode interface { // MethodGroup: Miner - MinerGetBaseInfo(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*api.MiningBaseInfo, error) //perm:read - MinerCreateBlock(context.Context, *api.BlockTemplate) (*types.BlockMsg, error) //perm:write + MinerGetBaseInfo(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*types.MiningBaseInfo, error) //perm:read + MinerCreateBlock(context.Context, *api.BlockTemplate) (*types.BlockMsg, error) //perm:write // // UX ? @@ -526,13 +526,13 @@ type FullNode interface { // StateListActors returns the addresses of every actor in the state StateListActors(context.Context, types.TipSetKey) ([]address.Address, error) //perm:read // StateMarketBalance looks up the Escrow and Locked balances of the given address in the Storage Market - StateMarketBalance(context.Context, address.Address, types.TipSetKey) (api.MarketBalance, error) //perm:read + StateMarketBalance(context.Context, address.Address, types.TipSetKey) (types.MarketBalance, error) //perm:read // StateMarketParticipants returns the Escrow and Locked balances of every participant in the Storage Market - StateMarketParticipants(context.Context, types.TipSetKey) (map[string]api.MarketBalance, error) //perm:read + StateMarketParticipants(context.Context, types.TipSetKey) (map[string]types.MarketBalance, error) //perm:read // StateMarketDeals returns information about every deal in the Storage Market - StateMarketDeals(context.Context, types.TipSetKey) (map[string]*api.MarketDeal, error) //perm:read + StateMarketDeals(context.Context, types.TipSetKey) (map[string]*types.MarketDeal, error) //perm:read // StateMarketStorageDeal returns information about the indicated deal - StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*api.MarketDeal, error) //perm:read + StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*types.MarketDeal, error) //perm:read // StateGetAllocationForPendingDeal returns the allocation for a given deal ID of a pending deal. StateGetAllocationForPendingDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*verifregtypes.Allocation, error) //perm:read // StateGetAllocation returns the allocation for a given address and allocation ID. @@ -614,7 +614,7 @@ type FullNode interface { StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error) //perm:read // StateVMCirculatingSupplyInternal returns an approximation of the circulating supply of Filecoin at the given tipset. // This is the value reported by the runtime interface to actors code. - StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error) //perm:read + StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (types.CirculatingSupply, error) //perm:read // StateNetworkVersion returns the network version at the given tipset StateNetworkVersion(context.Context, types.TipSetKey) (apitypes.NetworkVersion, error) //perm:read // StateActorCodeCIDs returns the CIDs of all the builtin actors for the given network version diff --git a/api/v0api/gateway.go b/api/v0api/gateway.go index 84efd3362dd..887355efc54 100644 --- a/api/v0api/gateway.go +++ b/api/v0api/gateway.go @@ -55,8 +55,8 @@ type Gateway interface { StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) - StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) - StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) + StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.MarketBalance, error) + StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*types.MarketDeal, error) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (api.MinerInfo, error) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) diff --git a/api/v0api/proxy_gen.go b/api/v0api/proxy_gen.go index 77e859aa07b..6497db3487a 100644 --- a/api/v0api/proxy_gen.go +++ b/api/v0api/proxy_gen.go @@ -165,7 +165,7 @@ type FullNodeStruct struct { MinerCreateBlock func(p0 context.Context, p1 *api.BlockTemplate) (*types.BlockMsg, error) `perm:"write"` - MinerGetBaseInfo func(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"` + MinerGetBaseInfo func(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*types.MiningBaseInfo, error) `perm:"read"` MpoolBatchPush func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` @@ -305,13 +305,13 @@ type FullNodeStruct struct { StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` - StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MarketBalance, error) `perm:"read"` + StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.MarketBalance, error) `perm:"read"` - StateMarketDeals func(p0 context.Context, p1 types.TipSetKey) (map[string]*api.MarketDeal, error) `perm:"read"` + StateMarketDeals func(p0 context.Context, p1 types.TipSetKey) (map[string]*types.MarketDeal, error) `perm:"read"` - StateMarketParticipants func(p0 context.Context, p1 types.TipSetKey) (map[string]api.MarketBalance, error) `perm:"read"` + StateMarketParticipants func(p0 context.Context, p1 types.TipSetKey) (map[string]types.MarketBalance, error) `perm:"read"` - StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*api.MarketDeal, error) `perm:"read"` + StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*types.MarketDeal, error) `perm:"read"` StateMinerActiveSectors func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` @@ -361,7 +361,7 @@ type FullNodeStruct struct { StateSectorPreCommitInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) `perm:"read"` - StateVMCirculatingSupplyInternal func(p0 context.Context, p1 types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"` + StateVMCirculatingSupplyInternal func(p0 context.Context, p1 types.TipSetKey) (types.CirculatingSupply, error) `perm:"read"` StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` @@ -467,9 +467,9 @@ type GatewayStruct struct { StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` - StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MarketBalance, error) `` + StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.MarketBalance, error) `` - StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*api.MarketDeal, error) `` + StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*types.MarketDeal, error) `` StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerInfo, error) `` @@ -1178,14 +1178,14 @@ func (s *FullNodeStub) MinerCreateBlock(p0 context.Context, p1 *api.BlockTemplat return nil, ErrNotSupported } -func (s *FullNodeStruct) MinerGetBaseInfo(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*api.MiningBaseInfo, error) { +func (s *FullNodeStruct) MinerGetBaseInfo(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*types.MiningBaseInfo, error) { if s.Internal.MinerGetBaseInfo == nil { return nil, ErrNotSupported } return s.Internal.MinerGetBaseInfo(p0, p1, p2, p3) } -func (s *FullNodeStub) MinerGetBaseInfo(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*api.MiningBaseInfo, error) { +func (s *FullNodeStub) MinerGetBaseInfo(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*types.MiningBaseInfo, error) { return nil, ErrNotSupported } @@ -1948,47 +1948,47 @@ func (s *FullNodeStub) StateLookupID(p0 context.Context, p1 address.Address, p2 return *new(address.Address), ErrNotSupported } -func (s *FullNodeStruct) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MarketBalance, error) { +func (s *FullNodeStruct) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.MarketBalance, error) { if s.Internal.StateMarketBalance == nil { - return *new(api.MarketBalance), ErrNotSupported + return *new(types.MarketBalance), ErrNotSupported } return s.Internal.StateMarketBalance(p0, p1, p2) } -func (s *FullNodeStub) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MarketBalance, error) { - return *new(api.MarketBalance), ErrNotSupported +func (s *FullNodeStub) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.MarketBalance, error) { + return *new(types.MarketBalance), ErrNotSupported } -func (s *FullNodeStruct) StateMarketDeals(p0 context.Context, p1 types.TipSetKey) (map[string]*api.MarketDeal, error) { +func (s *FullNodeStruct) StateMarketDeals(p0 context.Context, p1 types.TipSetKey) (map[string]*types.MarketDeal, error) { if s.Internal.StateMarketDeals == nil { - return *new(map[string]*api.MarketDeal), ErrNotSupported + return *new(map[string]*types.MarketDeal), ErrNotSupported } return s.Internal.StateMarketDeals(p0, p1) } -func (s *FullNodeStub) StateMarketDeals(p0 context.Context, p1 types.TipSetKey) (map[string]*api.MarketDeal, error) { - return *new(map[string]*api.MarketDeal), ErrNotSupported +func (s *FullNodeStub) StateMarketDeals(p0 context.Context, p1 types.TipSetKey) (map[string]*types.MarketDeal, error) { + return *new(map[string]*types.MarketDeal), ErrNotSupported } -func (s *FullNodeStruct) StateMarketParticipants(p0 context.Context, p1 types.TipSetKey) (map[string]api.MarketBalance, error) { +func (s *FullNodeStruct) StateMarketParticipants(p0 context.Context, p1 types.TipSetKey) (map[string]types.MarketBalance, error) { if s.Internal.StateMarketParticipants == nil { - return *new(map[string]api.MarketBalance), ErrNotSupported + return *new(map[string]types.MarketBalance), ErrNotSupported } return s.Internal.StateMarketParticipants(p0, p1) } -func (s *FullNodeStub) StateMarketParticipants(p0 context.Context, p1 types.TipSetKey) (map[string]api.MarketBalance, error) { - return *new(map[string]api.MarketBalance), ErrNotSupported +func (s *FullNodeStub) StateMarketParticipants(p0 context.Context, p1 types.TipSetKey) (map[string]types.MarketBalance, error) { + return *new(map[string]types.MarketBalance), ErrNotSupported } -func (s *FullNodeStruct) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*api.MarketDeal, error) { +func (s *FullNodeStruct) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*types.MarketDeal, error) { if s.Internal.StateMarketStorageDeal == nil { return nil, ErrNotSupported } return s.Internal.StateMarketStorageDeal(p0, p1, p2) } -func (s *FullNodeStub) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*api.MarketDeal, error) { +func (s *FullNodeStub) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*types.MarketDeal, error) { return nil, ErrNotSupported } @@ -2256,15 +2256,15 @@ func (s *FullNodeStub) StateSectorPreCommitInfo(p0 context.Context, p1 address.A return *new(miner.SectorPreCommitOnChainInfo), ErrNotSupported } -func (s *FullNodeStruct) StateVMCirculatingSupplyInternal(p0 context.Context, p1 types.TipSetKey) (api.CirculatingSupply, error) { +func (s *FullNodeStruct) StateVMCirculatingSupplyInternal(p0 context.Context, p1 types.TipSetKey) (types.CirculatingSupply, error) { if s.Internal.StateVMCirculatingSupplyInternal == nil { - return *new(api.CirculatingSupply), ErrNotSupported + return *new(types.CirculatingSupply), ErrNotSupported } return s.Internal.StateVMCirculatingSupplyInternal(p0, p1) } -func (s *FullNodeStub) StateVMCirculatingSupplyInternal(p0 context.Context, p1 types.TipSetKey) (api.CirculatingSupply, error) { - return *new(api.CirculatingSupply), ErrNotSupported +func (s *FullNodeStub) StateVMCirculatingSupplyInternal(p0 context.Context, p1 types.TipSetKey) (types.CirculatingSupply, error) { + return *new(types.CirculatingSupply), ErrNotSupported } func (s *FullNodeStruct) StateVerifiedClientStatus(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) { @@ -2784,25 +2784,25 @@ func (s *GatewayStub) StateLookupID(p0 context.Context, p1 address.Address, p2 t return *new(address.Address), ErrNotSupported } -func (s *GatewayStruct) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MarketBalance, error) { +func (s *GatewayStruct) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.MarketBalance, error) { if s.Internal.StateMarketBalance == nil { - return *new(api.MarketBalance), ErrNotSupported + return *new(types.MarketBalance), ErrNotSupported } return s.Internal.StateMarketBalance(p0, p1, p2) } -func (s *GatewayStub) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MarketBalance, error) { - return *new(api.MarketBalance), ErrNotSupported +func (s *GatewayStub) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.MarketBalance, error) { + return *new(types.MarketBalance), ErrNotSupported } -func (s *GatewayStruct) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*api.MarketDeal, error) { +func (s *GatewayStruct) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*types.MarketDeal, error) { if s.Internal.StateMarketStorageDeal == nil { return nil, ErrNotSupported } return s.Internal.StateMarketStorageDeal(p0, p1, p2) } -func (s *GatewayStub) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*api.MarketDeal, error) { +func (s *GatewayStub) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*types.MarketDeal, error) { return nil, ErrNotSupported } diff --git a/api/v0api/v0mocks/mock_full.go b/api/v0api/v0mocks/mock_full.go index 5183e6418e5..0316b16509c 100644 --- a/api/v0api/v0mocks/mock_full.go +++ b/api/v0api/v0mocks/mock_full.go @@ -1106,10 +1106,10 @@ func (mr *MockFullNodeMockRecorder) MinerCreateBlock(arg0, arg1 interface{}) *go } // MinerGetBaseInfo mocks base method. -func (m *MockFullNode) MinerGetBaseInfo(arg0 context.Context, arg1 address.Address, arg2 abi.ChainEpoch, arg3 types.TipSetKey) (*api.MiningBaseInfo, error) { +func (m *MockFullNode) MinerGetBaseInfo(arg0 context.Context, arg1 address.Address, arg2 abi.ChainEpoch, arg3 types.TipSetKey) (*types.MiningBaseInfo, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "MinerGetBaseInfo", arg0, arg1, arg2, arg3) - ret0, _ := ret[0].(*api.MiningBaseInfo) + ret0, _ := ret[0].(*types.MiningBaseInfo) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -2535,10 +2535,10 @@ func (mr *MockFullNodeMockRecorder) StateLookupID(arg0, arg1, arg2 interface{}) } // StateMarketBalance mocks base method. -func (m *MockFullNode) StateMarketBalance(arg0 context.Context, arg1 address.Address, arg2 types.TipSetKey) (api.MarketBalance, error) { +func (m *MockFullNode) StateMarketBalance(arg0 context.Context, arg1 address.Address, arg2 types.TipSetKey) (types.MarketBalance, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateMarketBalance", arg0, arg1, arg2) - ret0, _ := ret[0].(api.MarketBalance) + ret0, _ := ret[0].(types.MarketBalance) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -2550,10 +2550,10 @@ func (mr *MockFullNodeMockRecorder) StateMarketBalance(arg0, arg1, arg2 interfac } // StateMarketDeals mocks base method. -func (m *MockFullNode) StateMarketDeals(arg0 context.Context, arg1 types.TipSetKey) (map[string]*api.MarketDeal, error) { +func (m *MockFullNode) StateMarketDeals(arg0 context.Context, arg1 types.TipSetKey) (map[string]*types.MarketDeal, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateMarketDeals", arg0, arg1) - ret0, _ := ret[0].(map[string]*api.MarketDeal) + ret0, _ := ret[0].(map[string]*types.MarketDeal) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -2565,10 +2565,10 @@ func (mr *MockFullNodeMockRecorder) StateMarketDeals(arg0, arg1 interface{}) *go } // StateMarketParticipants mocks base method. -func (m *MockFullNode) StateMarketParticipants(arg0 context.Context, arg1 types.TipSetKey) (map[string]api.MarketBalance, error) { +func (m *MockFullNode) StateMarketParticipants(arg0 context.Context, arg1 types.TipSetKey) (map[string]types.MarketBalance, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateMarketParticipants", arg0, arg1) - ret0, _ := ret[0].(map[string]api.MarketBalance) + ret0, _ := ret[0].(map[string]types.MarketBalance) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -2580,10 +2580,10 @@ func (mr *MockFullNodeMockRecorder) StateMarketParticipants(arg0, arg1 interface } // StateMarketStorageDeal mocks base method. -func (m *MockFullNode) StateMarketStorageDeal(arg0 context.Context, arg1 abi.DealID, arg2 types.TipSetKey) (*api.MarketDeal, error) { +func (m *MockFullNode) StateMarketStorageDeal(arg0 context.Context, arg1 abi.DealID, arg2 types.TipSetKey) (*types.MarketDeal, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateMarketStorageDeal", arg0, arg1, arg2) - ret0, _ := ret[0].(*api.MarketDeal) + ret0, _ := ret[0].(*types.MarketDeal) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -2955,10 +2955,10 @@ func (mr *MockFullNodeMockRecorder) StateSectorPreCommitInfo(arg0, arg1, arg2, a } // StateVMCirculatingSupplyInternal mocks base method. -func (m *MockFullNode) StateVMCirculatingSupplyInternal(arg0 context.Context, arg1 types.TipSetKey) (api.CirculatingSupply, error) { +func (m *MockFullNode) StateVMCirculatingSupplyInternal(arg0 context.Context, arg1 types.TipSetKey) (types.CirculatingSupply, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateVMCirculatingSupplyInternal", arg0, arg1) - ret0, _ := ret[0].(api.CirculatingSupply) + ret0, _ := ret[0].(types.CirculatingSupply) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 30b054da07e72138e92cd5ec6413fedf223cf5b7..915e0443bf227411ed93d2b3c79e3f62e898fe43 100644 GIT binary patch delta 20616 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 T_Rs$V00960V9!zwmLvuMu{(?% diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index 04c3ff16f359dca878353109be90593a95165bff..a6761cb022209c3949d317de40a69fb51dad872b 100644 GIT binary patch literal 4989 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 Hsqp{+jtlZT literal 4982 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 delta 13893 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 O0RR8|yuJk4ECB#@5y0pG delta 1928 zcmV;32Y2|MDV`~?4+DQa)}}1+V1{*uO-|ksO;u9~@b!U-QxNhOPh3l@xbq~}6*KI!%%Z6q+7Ll28dGSmEyz|J3ZCk;l zaRHs1bRs4wWBYgM7oTkdG68wre@5KKkRY#P;g&tTG4~dw4*Z*kpoPiIL+%4M(1{mR=$&|-snS!mPEXbJ zz9dWkLeNC6C!G@CvQ|tN9Y~qwT_lvK`wOSmZOV-SBS-dsqh+8)q0)HN#bm~G>@R5f zDCbR{KBi$Z>bXZv-u0-jqHZivXjQEhOh_=H*T#f~T0Rr{mB5LGcqg$@t{l$u7Q6|W zO)(jXGUqdpu*WzE$5xbsnMI!6M<8_+b+RM*1qpsJaot1{GBM?Gu6 zo1mwHo(g*U8tLilrFt2sn`2Vh6s3%450|TK6-T38H7Hq2`Ac8Pv#AGb1b_7M56k{y zKcFjWyD+$CfalEYSWe!HWz)}@G=Bz{S90An8wcc&-zHn6$<19t zQuPKBarLUWdiAw|+EC30wF^k+9w(dydGhaoh~Li>fdNas3z~w`c3vBmTO=1YttD>c zE{FmFcivr;OjqiPIHWtX>%v;xz0Z3B7U74p1LOSx<~kvZR( zeIJ|M>+9XjGFi|LJKmJWXSr!P^G!I+$gs){u5bdZB4AI!W6)~gg*^FXFpI8{Goyso z5F@H&N|J^w(i#W4)73 z4gCV?my=BnX8{J2wGLMT4vUix4_N_JlV}f30_x+Fw-1ni17#nt=8dzA<*a_p}t$+hD+L0K}hQJxHvO2#z5*hTs^CV~h&UyGo#Cm09&RbM=Y!7Otz! zt+z5f3#kx)GwilmYa0kffjYlLRv`dT0N`r_z;VH;an+8CJN%rurVfbPcQV{(e2-G6 z-N|6$Q?NNQjzrPXv2);<6`0tA6N}X?&Vc(#&VW;uf-~T*5dD<|+Q4l$>x@Ngabnxn zj`;j-0f)xuCq&s1r@yUm0o{8K&^cOL1@r(4-<_;~t)mNmw<(}=$o|0|@DQb#%x=j7 zE&+x22tY7JkHABQO-v6^8!-0{XOJTH2Zi1}VCruAR*hc;uwE@?R7^u-tYLj{sR+9- zZ8N=s!(y)HJ~iz}ZlsB_B-MEW+E1s| zTEUlnkpg@~6dLpQIh|5UtvA^@y<#eNP1+onrjZlXe>&~a3qD;-boc>oF;>8#o-tNb zt?DHFnrl*V3m08mq4yL{FXf)}dsit&vbBH<<4H=y=9H_&oK7oBWl1`-)6H<8MKspZ= zE_d7tS5vHTTa95@6z>^o#3eG3VL|s0t4Nkn^UWW zx}Y2?^tAC9LPhVW1GV4L^+~TYfu`P>n96X{A5T=(&?}?G&OH~gtnq9%Iw}ZK`xAQi zAH&5jPRoqtEF@tFS`>QsUQkVV&tIV}#>zX?0+XUOPr)+HEJ??ryTXlNxA8<3lB7b+{dqK)*b*DCKl z%OPXM4YowBqZ!#l8eZL37TF^c#M$}cwkZ**Dk4>DW1DJ008wPioJ=#yl|M_{xQAk% z7bV%j@uC!5)NU(PBilShUA28*-Vlyzy^*d|M$(olq*f52^f$!xKR!m3QzbX~_@Xy9 z*$!R)ir1g7e%q=hmTla7z$X-2fX build.UpgradeAssemblyHeight { filReserveDisbursed, err = GetFilReserveDisbursed(ctx, st) if err != nil { - return api.CirculatingSupply{}, xerrors.Errorf("failed to calculate filReserveDisbursed: %w", err) + return types.CirculatingSupply{}, xerrors.Errorf("failed to calculate filReserveDisbursed: %w", err) } } filMined, err := GetFilMined(ctx, st) if err != nil { - return api.CirculatingSupply{}, xerrors.Errorf("failed to calculate filMined: %w", err) + return types.CirculatingSupply{}, xerrors.Errorf("failed to calculate filMined: %w", err) } filBurnt, err := GetFilBurnt(ctx, st) if err != nil { - return api.CirculatingSupply{}, xerrors.Errorf("failed to calculate filBurnt: %w", err) + return types.CirculatingSupply{}, xerrors.Errorf("failed to calculate filBurnt: %w", err) } filLocked, err := GetFilLocked(ctx, st) if err != nil { - return api.CirculatingSupply{}, xerrors.Errorf("failed to calculate filLocked: %w", err) + return types.CirculatingSupply{}, xerrors.Errorf("failed to calculate filLocked: %w", err) } ret := types.BigAdd(filVested, filMined) @@ -376,7 +375,7 @@ func (sm *StateManager) GetVMCirculatingSupplyDetailed(ctx context.Context, heig ret = big.Zero() } - return api.CirculatingSupply{ + return types.CirculatingSupply{ FilVested: filVested, FilMined: filMined, FilBurnt: filBurnt, diff --git a/chain/types/market_deal.go b/chain/types/market_deal.go new file mode 100644 index 00000000000..2a6cf8b88a3 --- /dev/null +++ b/chain/types/market_deal.go @@ -0,0 +1,16 @@ +package types + +import ( + "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/go-state-types/builtin/v9/market" +) + +type MarketDeal struct { + Proposal market.DealProposal + State market.DealState +} + +type MarketBalance struct { + Escrow big.Int + Locked big.Int +} diff --git a/chain/types/mining_base_info.go b/chain/types/mining_base_info.go new file mode 100644 index 00000000000..d516cf88fa2 --- /dev/null +++ b/chain/types/mining_base_info.go @@ -0,0 +1,18 @@ +package types + +import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/builtin" +) + +type MiningBaseInfo struct { + MinerPower BigInt + NetworkPower BigInt + Sectors []builtin.ExtendedSectorInfo + WorkerKey address.Address + SectorSize abi.SectorSize + PrevBeaconEntry BeaconEntry + BeaconEntries []BeaconEntry + EligibleForMining bool +} diff --git a/chain/types/supply.go b/chain/types/supply.go new file mode 100644 index 00000000000..8a43a9375df --- /dev/null +++ b/chain/types/supply.go @@ -0,0 +1,12 @@ +package types + +import "github.com/filecoin-project/go-state-types/abi" + +type CirculatingSupply struct { + FilVested abi.TokenAmount + FilMined abi.TokenAmount + FilBurnt abi.TokenAmount + FilLocked abi.TokenAmount + FilCirculating abi.TokenAmount + FilReserveDisbursed abi.TokenAmount +} diff --git a/cli/wallet_test.go b/cli/wallet_test.go index dee26018b28..d57110ba307 100644 --- a/cli/wallet_test.go +++ b/cli/wallet_test.go @@ -103,7 +103,7 @@ func TestWalletList(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - balance := api.MarketBalance{ + balance := types.MarketBalance{ Escrow: big.NewInt(1234), Locked: big.NewInt(123), } @@ -281,7 +281,7 @@ func TestWalletMarketWithdraw(t *testing.T) { addr, err := address.NewIDAddress(1234) assert.NoError(t, err) - balance := api.MarketBalance{ + balance := types.MarketBalance{ Escrow: big.NewInt(100), Locked: big.NewInt(10), } diff --git a/cmd/tvx/simulate.go b/cmd/tvx/simulate.go index ea7b67a662d..d8ab9fa2042 100644 --- a/cmd/tvx/simulate.go +++ b/cmd/tvx/simulate.go @@ -102,7 +102,7 @@ func runSimulateCmd(_ *cli.Context) error { preroot = ts.ParentState() epoch = ts.Height() baseFee = ts.Blocks()[0].ParentBaseFee - circSupply api.CirculatingSupply + circSupply types.CirculatingSupply ) // Get circulating supply. diff --git a/gateway/node.go b/gateway/node.go index 7e4972cb012..5785eb1db73 100644 --- a/gateway/node.go +++ b/gateway/node.go @@ -72,8 +72,8 @@ type TargetAPI interface { StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) - StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) - StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) + StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.MarketBalance, error) + StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*types.MarketDeal, error) StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error) StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) @@ -88,7 +88,7 @@ type TargetAPI interface { StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error) StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) - StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error) + StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (types.CirculatingSupply, error) WalletBalance(context.Context, address.Address) (types.BigInt, error) //perm:read } @@ -452,17 +452,17 @@ func (gw *Node) StateLookupID(ctx context.Context, addr address.Address, tsk typ return gw.target.StateLookupID(ctx, addr, tsk) } -func (gw *Node) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) { +func (gw *Node) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.MarketBalance, error) { if err := gw.limit(ctx, stateRateLimitTokens); err != nil { - return api.MarketBalance{}, err + return types.MarketBalance{}, err } if err := gw.checkTipsetKey(ctx, tsk); err != nil { - return api.MarketBalance{}, err + return types.MarketBalance{}, err } return gw.target.StateMarketBalance(ctx, addr, tsk) } -func (gw *Node) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) { +func (gw *Node) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*types.MarketDeal, error) { if err := gw.limit(ctx, stateRateLimitTokens); err != nil { return nil, err } @@ -621,12 +621,12 @@ func (gw *Node) StateVerifiedClientStatus(ctx context.Context, addr address.Addr return gw.target.StateVerifiedClientStatus(ctx, addr, tsk) } -func (gw *Node) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) { +func (gw *Node) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (types.CirculatingSupply, error) { if err := gw.limit(ctx, stateRateLimitTokens); err != nil { - return api.CirculatingSupply{}, err + return types.CirculatingSupply{}, err } if err := gw.checkTipsetKey(ctx, tsk); err != nil { - return api.CirculatingSupply{}, err + return types.CirculatingSupply{}, err } return gw.target.StateVMCirculatingSupplyInternal(ctx, tsk) } diff --git a/gateway/node_test.go b/gateway/node_test.go index 805767dc627..17e053cf915 100644 --- a/gateway/node_test.go +++ b/gateway/node_test.go @@ -134,11 +134,11 @@ func (m *mockGatewayDepsAPI) StateListMiners(ctx context.Context, tsk types.TipS panic("implement me") } -func (m *mockGatewayDepsAPI) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) { +func (m *mockGatewayDepsAPI) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.MarketBalance, error) { panic("implement me") } -func (m *mockGatewayDepsAPI) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) { +func (m *mockGatewayDepsAPI) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*types.MarketDeal, error) { panic("implement me") } diff --git a/markets/retrievaladapter/provider_test.go b/markets/retrievaladapter/provider_test.go index b7b5039d674..e5e1cf9e2df 100644 --- a/markets/retrievaladapter/provider_test.go +++ b/markets/retrievaladapter/provider_test.go @@ -14,7 +14,6 @@ import ( testnet "github.com/filecoin-project/go-fil-markets/shared_testutil" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api/mocks" "github.com/filecoin-project/lotus/chain/actors/builtin/market" "github.com/filecoin-project/lotus/chain/types" @@ -49,12 +48,12 @@ func TestGetPricingInput(t *testing.T) { "error when no piece matches": { fFnc: func(n *mocks.MockFullNode) { - out1 := &api.MarketDeal{ + out1 := &types.MarketDeal{ Proposal: market.DealProposal{ PieceCID: testnet.GenerateCids(1)[0], }, } - out2 := &api.MarketDeal{ + out2 := &types.MarketDeal{ Proposal: market.DealProposal{ PieceCID: testnet.GenerateCids(1)[0], }, @@ -72,13 +71,13 @@ func TestGetPricingInput(t *testing.T) { "error when fails to fetch deal state": { fFnc: func(n *mocks.MockFullNode) { - out1 := &api.MarketDeal{ + out1 := &types.MarketDeal{ Proposal: market.DealProposal{ PieceCID: pcid, PieceSize: paddedSize, }, } - out2 := &api.MarketDeal{ + out2 := &types.MarketDeal{ Proposal: market.DealProposal{ PieceCID: testnet.GenerateCids(1)[0], VerifiedDeal: true, @@ -97,13 +96,13 @@ func TestGetPricingInput(t *testing.T) { "verified is true even if one deal is verified and we get the correct piecesize": { fFnc: func(n *mocks.MockFullNode) { - out1 := &api.MarketDeal{ + out1 := &types.MarketDeal{ Proposal: market.DealProposal{ PieceCID: pcid, PieceSize: paddedSize, }, } - out2 := &api.MarketDeal{ + out2 := &types.MarketDeal{ Proposal: market.DealProposal{ PieceCID: testnet.GenerateCids(1)[0], VerifiedDeal: true, @@ -123,12 +122,12 @@ func TestGetPricingInput(t *testing.T) { "success even if one deal state fetch errors out but the other deal is verified and has the required piececid": { fFnc: func(n *mocks.MockFullNode) { - out1 := &api.MarketDeal{ + out1 := &types.MarketDeal{ Proposal: market.DealProposal{ PieceCID: testnet.GenerateCids(1)[0], }, } - out2 := &api.MarketDeal{ + out2 := &types.MarketDeal{ Proposal: market.DealProposal{ PieceCID: pcid, PieceSize: paddedSize, @@ -149,14 +148,14 @@ func TestGetPricingInput(t *testing.T) { "verified is false if both deals are unverified and we get the correct piece size": { fFnc: func(n *mocks.MockFullNode) { - out1 := &api.MarketDeal{ + out1 := &types.MarketDeal{ Proposal: market.DealProposal{ PieceCID: pcid, PieceSize: paddedSize, VerifiedDeal: false, }, } - out2 := &api.MarketDeal{ + out2 := &types.MarketDeal{ Proposal: market.DealProposal{ PieceCID: testnet.GenerateCids(1)[0], VerifiedDeal: false, diff --git a/markets/storageadapter/ondealsectorcommitted_test.go b/markets/storageadapter/ondealsectorcommitted_test.go index 1d7519ff9f9..b05bdb752fa 100644 --- a/markets/storageadapter/ondealsectorcommitted_test.go +++ b/markets/storageadapter/ondealsectorcommitted_test.go @@ -23,7 +23,6 @@ import ( "github.com/filecoin-project/go-state-types/cbor" tutils "github.com/filecoin-project/specs-actors/v2/support/testing" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors/builtin/market" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/events" @@ -53,21 +52,21 @@ func TestOnDealSectorPreCommitted(t *testing.T) { ClientCollateral: abi.NewTokenAmount(1), Label: label, } - unfinishedDeal := &api.MarketDeal{ + unfinishedDeal := &types.MarketDeal{ Proposal: proposal, State: market.DealState{ SectorStartEpoch: -1, LastUpdatedEpoch: 2, }, } - activeDeal := &api.MarketDeal{ + activeDeal := &types.MarketDeal{ Proposal: proposal, State: market.DealState{ SectorStartEpoch: 1, LastUpdatedEpoch: 2, }, } - slashedDeal := &api.MarketDeal{ + slashedDeal := &types.MarketDeal{ Proposal: proposal, State: market.DealState{ SectorStartEpoch: 1, @@ -275,21 +274,21 @@ func TestOnDealSectorCommitted(t *testing.T) { ClientCollateral: abi.NewTokenAmount(1), Label: label, } - unfinishedDeal := &api.MarketDeal{ + unfinishedDeal := &types.MarketDeal{ Proposal: proposal, State: market.DealState{ SectorStartEpoch: -1, LastUpdatedEpoch: 2, }, } - activeDeal := &api.MarketDeal{ + activeDeal := &types.MarketDeal{ Proposal: proposal, State: market.DealState{ SectorStartEpoch: 1, LastUpdatedEpoch: 2, }, } - slashedDeal := &api.MarketDeal{ + slashedDeal := &types.MarketDeal{ Proposal: proposal, State: market.DealState{ SectorStartEpoch: 1, diff --git a/markets/utils/converters.go b/markets/utils/converters.go index 9562de695fc..3c4f6edde29 100644 --- a/markets/utils/converters.go +++ b/markets/utils/converters.go @@ -1,6 +1,7 @@ package utils import ( + "github.com/filecoin-project/lotus/chain/types" "github.com/libp2p/go-libp2p/core/peer" "github.com/multiformats/go-multiaddr" @@ -8,8 +9,6 @@ import ( "github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - - "github.com/filecoin-project/lotus/api" ) func NewStorageProviderInfo(address address.Address, miner address.Address, sectorSize abi.SectorSize, peer peer.ID, addrs []abi.Multiaddrs) storagemarket.StorageProviderInfo { @@ -31,7 +30,7 @@ func NewStorageProviderInfo(address address.Address, miner address.Address, sect } } -func ToSharedBalance(bal api.MarketBalance) storagemarket.Balance { +func ToSharedBalance(bal types.MarketBalance) storagemarket.Balance { return storagemarket.Balance{ Locked: bal.Locked, Available: big.Sub(bal.Escrow, bal.Locked), diff --git a/miner/miner.go b/miner/miner.go index f954352ae45..c9ed20813b1 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -428,7 +428,7 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (minedBlock *type // always write out a log var winner *types.ElectionProof - var mbi *api.MiningBaseInfo + var mbi *types.MiningBaseInfo var rbase types.BeaconEntry defer func() { @@ -438,7 +438,7 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (minedBlock *type // in the current deadline. If this case - put together a dummy one for reporting // https://github.com/filecoin-project/lotus/blob/v1.9.0/chain/stmgr/utils.go#L500-L502 if mbi == nil { - mbi = &api.MiningBaseInfo{ + mbi = &types.MiningBaseInfo{ NetworkPower: big.NewInt(-1), // we do not know how big the network is at this point EligibleForMining: false, MinerPower: big.NewInt(0), // but we do know we do not have anything eligible @@ -583,7 +583,7 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (minedBlock *type return minedBlock, nil } -func (m *Miner) computeTicket(ctx context.Context, brand *types.BeaconEntry, base *MiningBase, mbi *api.MiningBaseInfo) (*types.Ticket, error) { +func (m *Miner) computeTicket(ctx context.Context, brand *types.BeaconEntry, base *MiningBase, mbi *types.MiningBaseInfo) (*types.Ticket, error) { buf := new(bytes.Buffer) if err := m.address.MarshalCBOR(buf); err != nil { return nil, xerrors.Errorf("failed to marshal address to cbor: %w", err) diff --git a/node/impl/full/state.go b/node/impl/full/state.go index d6402f46a8e..5cbea717756 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -61,8 +61,8 @@ type StateModuleAPI interface { StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) - StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) - StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) + StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.MarketBalance, error) + StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*types.MarketDeal, error) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (api.MinerInfo, error) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) @@ -575,7 +575,7 @@ func (a *StateAPI) StateEncodeParams(ctx context.Context, toActCode cid.Cid, met } // This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner -func (a *StateAPI) MinerGetBaseInfo(ctx context.Context, maddr address.Address, epoch abi.ChainEpoch, tsk types.TipSetKey) (*api.MiningBaseInfo, error) { +func (a *StateAPI) MinerGetBaseInfo(ctx context.Context, maddr address.Address, epoch abi.ChainEpoch, tsk types.TipSetKey) (*types.MiningBaseInfo, error) { // XXX: Gets the state by computing the tipset state, instead of looking at the parent. return stmgr.MinerGetBaseInfo(ctx, a.StateManager, a.Beacon, tsk, epoch, maddr, a.ProofVerifier) } @@ -683,16 +683,16 @@ func (a *StateAPI) StateListActors(ctx context.Context, tsk types.TipSetKey) ([] return a.StateManager.ListAllActors(ctx, ts) } -func (m *StateModule) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) { +func (m *StateModule) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.MarketBalance, error) { ts, err := m.Chain.GetTipSetFromKey(ctx, tsk) if err != nil { - return api.MarketBalance{}, xerrors.Errorf("loading tipset %s: %w", tsk, err) + return types.MarketBalance{}, xerrors.Errorf("loading tipset %s: %w", tsk, err) } return m.StateManager.MarketBalance(ctx, addr, ts) } -func (a *StateAPI) StateMarketParticipants(ctx context.Context, tsk types.TipSetKey) (map[string]api.MarketBalance, error) { - out := map[string]api.MarketBalance{} +func (a *StateAPI) StateMarketParticipants(ctx context.Context, tsk types.TipSetKey) (map[string]types.MarketBalance, error) { + out := map[string]types.MarketBalance{} ts, err := a.Chain.GetTipSetFromKey(ctx, tsk) if err != nil { @@ -719,7 +719,7 @@ func (a *StateAPI) StateMarketParticipants(ctx context.Context, tsk types.TipSet return err } - out[a.String()] = api.MarketBalance{ + out[a.String()] = types.MarketBalance{ Escrow: es, Locked: lk, } @@ -731,8 +731,8 @@ func (a *StateAPI) StateMarketParticipants(ctx context.Context, tsk types.TipSet return out, nil } -func (a *StateAPI) StateMarketDeals(ctx context.Context, tsk types.TipSetKey) (map[string]*api.MarketDeal, error) { - out := map[string]*api.MarketDeal{} +func (a *StateAPI) StateMarketDeals(ctx context.Context, tsk types.TipSetKey) (map[string]*types.MarketDeal, error) { + out := map[string]*types.MarketDeal{} ts, err := a.Chain.GetTipSetFromKey(ctx, tsk) if err != nil { @@ -761,7 +761,7 @@ func (a *StateAPI) StateMarketDeals(ctx context.Context, tsk types.TipSetKey) (m } else if !found { s = market.EmptyDealState() } - out[strconv.FormatInt(int64(dealID), 10)] = &api.MarketDeal{ + out[strconv.FormatInt(int64(dealID), 10)] = &types.MarketDeal{ Proposal: d, State: *s, } @@ -772,7 +772,7 @@ func (a *StateAPI) StateMarketDeals(ctx context.Context, tsk types.TipSetKey) (m return out, nil } -func (m *StateModule) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) { +func (m *StateModule) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*types.MarketDeal, error) { ts, err := m.Chain.GetTipSetFromKey(ctx, tsk) if err != nil { return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) @@ -1685,7 +1685,7 @@ func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetK return a.StateManager.GetCirculatingSupply(ctx, ts.Height()-1, sTree) } -func (a *StateAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) { +func (a *StateAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (types.CirculatingSupply, error) { return stateVMCirculatingSupplyInternal(ctx, tsk, a.Chain, a.StateManager) } func stateVMCirculatingSupplyInternal( @@ -1693,15 +1693,15 @@ func stateVMCirculatingSupplyInternal( tsk types.TipSetKey, cstore *store.ChainStore, smgr *stmgr.StateManager, -) (api.CirculatingSupply, error) { +) (types.CirculatingSupply, error) { ts, err := cstore.GetTipSetFromKey(ctx, tsk) if err != nil { - return api.CirculatingSupply{}, xerrors.Errorf("loading tipset %s: %w", tsk, err) + return types.CirculatingSupply{}, xerrors.Errorf("loading tipset %s: %w", tsk, err) } sTree, err := smgr.ParentState(ts) if err != nil { - return api.CirculatingSupply{}, err + return types.CirculatingSupply{}, err } return smgr.GetVMCirculatingSupplyDetailed(ctx, ts.Height(), sTree) diff --git a/node/impl/storminer.go b/node/impl/storminer.go index 56aa7afded3..fed035607b7 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -513,7 +513,7 @@ func (sm *StorageMinerAPI) MarketImportDealData(ctx context.Context, propCid cid return sm.StorageProvider.ImportDataForDeal(ctx, propCid, fi) } -func (sm *StorageMinerAPI) listDeals(ctx context.Context) ([]*api.MarketDeal, error) { +func (sm *StorageMinerAPI) listDeals(ctx context.Context) ([]*types.MarketDeal, error) { ts, err := sm.Full.ChainHead(ctx) if err != nil { return nil, err @@ -524,7 +524,7 @@ func (sm *StorageMinerAPI) listDeals(ctx context.Context) ([]*api.MarketDeal, er return nil, err } - var out []*api.MarketDeal + var out []*types.MarketDeal for _, deal := range allDeals { if deal.Proposal.Provider == sm.Miner.Address() { @@ -535,7 +535,7 @@ func (sm *StorageMinerAPI) listDeals(ctx context.Context) ([]*api.MarketDeal, er return out, nil } -func (sm *StorageMinerAPI) MarketListDeals(ctx context.Context) ([]*api.MarketDeal, error) { +func (sm *StorageMinerAPI) MarketListDeals(ctx context.Context) ([]*types.MarketDeal, error) { return sm.listDeals(ctx) } @@ -1160,7 +1160,7 @@ func (sm *StorageMinerAPI) DagstoreLookupPieces(ctx context.Context, cid cid.Cid return ret, nil } -func (sm *StorageMinerAPI) DealsList(ctx context.Context) ([]*api.MarketDeal, error) { +func (sm *StorageMinerAPI) DealsList(ctx context.Context) ([]*types.MarketDeal, error) { return sm.listDeals(ctx) } diff --git a/storage/pipeline/currentdealinfo.go b/storage/pipeline/currentdealinfo.go index cd3aa47be27..14f9c3fd96e 100644 --- a/storage/pipeline/currentdealinfo.go +++ b/storage/pipeline/currentdealinfo.go @@ -22,14 +22,14 @@ import ( type CurrentDealInfoAPI interface { ChainGetMessage(context.Context, cid.Cid) (*types.Message, error) StateLookupID(context.Context, address.Address, types.TipSetKey) (address.Address, error) - StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*api.MarketDeal, error) + StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*types.MarketDeal, error) StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) } type CurrentDealInfo struct { DealID abi.DealID - MarketDeal *api.MarketDeal + MarketDeal *types.MarketDeal PublishMsgTipSet types.TipSetKey } diff --git a/storage/pipeline/currentdealinfo_test.go b/storage/pipeline/currentdealinfo_test.go index 21141a35d57..f3fc9e9b698 100644 --- a/storage/pipeline/currentdealinfo_test.go +++ b/storage/pipeline/currentdealinfo_test.go @@ -78,21 +78,21 @@ func TestGetCurrentDealInfo(t *testing.T) { ClientCollateral: abi.NewTokenAmount(1), Label: another, } - successDeal := &api.MarketDeal{ + successDeal := &types.MarketDeal{ Proposal: proposal, State: market.DealState{ SectorStartEpoch: 1, LastUpdatedEpoch: 2, }, } - earlierDeal := &api.MarketDeal{ + earlierDeal := &types.MarketDeal{ Proposal: otherProposal, State: market.DealState{ SectorStartEpoch: 1, LastUpdatedEpoch: 2, }, } - anotherDeal := &api.MarketDeal{ + anotherDeal := &types.MarketDeal{ Proposal: anotherProposal, State: market.DealState{ SectorStartEpoch: 1, @@ -103,11 +103,11 @@ func TestGetCurrentDealInfo(t *testing.T) { type testCaseData struct { searchMessageLookup *api.MsgLookup searchMessageErr error - marketDeals map[abi.DealID]*api.MarketDeal + marketDeals map[abi.DealID]*types.MarketDeal publishCid cid.Cid targetProposal *market.DealProposal expectedDealID abi.DealID - expectedMarketDeal *api.MarketDeal + expectedMarketDeal *types.MarketDeal expectedError error networkVersion network.Version } @@ -120,7 +120,7 @@ func TestGetCurrentDealInfo(t *testing.T) { Return: makePublishDealsReturnBytesOldVersion(t, []abi.DealID{successDealID}), }, }, - marketDeals: map[abi.DealID]*api.MarketDeal{ + marketDeals: map[abi.DealID]*types.MarketDeal{ successDealID: successDeal, }, targetProposal: &proposal, @@ -135,7 +135,7 @@ func TestGetCurrentDealInfo(t *testing.T) { Return: makePublishDealsReturnBytesOldVersion(t, []abi.DealID{earlierDealID, successDealID}), }, }, - marketDeals: map[abi.DealID]*api.MarketDeal{ + marketDeals: map[abi.DealID]*types.MarketDeal{ earlierDealID: earlierDeal, successDealID: successDeal, }, @@ -151,7 +151,7 @@ func TestGetCurrentDealInfo(t *testing.T) { Return: makePublishDealsReturnBytesOldVersion(t, []abi.DealID{earlierDealID}), }, }, - marketDeals: map[abi.DealID]*api.MarketDeal{ + marketDeals: map[abi.DealID]*types.MarketDeal{ earlierDealID: earlierDeal, }, targetProposal: &proposal, @@ -166,7 +166,7 @@ func TestGetCurrentDealInfo(t *testing.T) { Return: makePublishDealsReturnBytesOldVersion(t, []abi.DealID{earlierDealID}), }, }, - marketDeals: map[abi.DealID]*api.MarketDeal{ + marketDeals: map[abi.DealID]*types.MarketDeal{ earlierDealID: earlierDeal, successDealID: successDeal, }, @@ -183,7 +183,7 @@ func TestGetCurrentDealInfo(t *testing.T) { Return: makePublishDealsReturn(t, []abi.DealID{earlierDealID}, []uint64{0}), }, }, - marketDeals: map[abi.DealID]*api.MarketDeal{ + marketDeals: map[abi.DealID]*types.MarketDeal{ earlierDealID: earlierDeal, successDealID: successDeal, }, @@ -201,7 +201,7 @@ func TestGetCurrentDealInfo(t *testing.T) { Return: makePublishDealsReturn(t, []abi.DealID{anotherDealID, successDealID}, []uint64{0, 2}), }, }, - marketDeals: map[abi.DealID]*api.MarketDeal{ + marketDeals: map[abi.DealID]*types.MarketDeal{ anotherDealID: anotherDeal, earlierDealID: earlierDeal, successDealID: successDeal, @@ -220,7 +220,7 @@ func TestGetCurrentDealInfo(t *testing.T) { Return: makePublishDealsReturnBytesOldVersion(t, []abi.DealID{successDealID}), }, }, - marketDeals: map[abi.DealID]*api.MarketDeal{ + marketDeals: map[abi.DealID]*types.MarketDeal{ successDealID: successDeal, }, targetProposal: nil, @@ -235,7 +235,7 @@ func TestGetCurrentDealInfo(t *testing.T) { Return: makePublishDealsReturnBytesOldVersion(t, []abi.DealID{earlierDealID, successDealID}), }, }, - marketDeals: map[abi.DealID]*api.MarketDeal{ + marketDeals: map[abi.DealID]*types.MarketDeal{ earlierDealID: earlierDeal, successDealID: successDeal, }, @@ -286,7 +286,7 @@ func TestGetCurrentDealInfo(t *testing.T) { defer cancel() ts, err := evtmock.MockTipset(address.TestAddress, rand.Uint64()) require.NoError(t, err) - marketDeals := make(map[marketDealKey]*api.MarketDeal) + marketDeals := make(map[marketDealKey]*types.MarketDeal) for dealID, deal := range data.marketDeals { marketDeals[marketDealKey{dealID, ts.Key()}] = deal } @@ -322,7 +322,7 @@ type CurrentDealInfoMockAPI struct { SearchMessageLookup *api.MsgLookup SearchMessageErr error - MarketDeals map[marketDealKey]*api.MarketDeal + MarketDeals map[marketDealKey]*types.MarketDeal Version network.Version } @@ -363,7 +363,7 @@ func (mapi *CurrentDealInfoMockAPI) StateLookupID(ctx context.Context, addr addr return addr, nil } -func (mapi *CurrentDealInfoMockAPI) StateMarketStorageDeal(ctx context.Context, dealID abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) { +func (mapi *CurrentDealInfoMockAPI) StateMarketStorageDeal(ctx context.Context, dealID abi.DealID, tsk types.TipSetKey) (*types.MarketDeal, error) { deal, ok := mapi.MarketDeals[marketDealKey{dealID, tsk}] if !ok { return nil, errNotFound diff --git a/storage/pipeline/mocks/api.go b/storage/pipeline/mocks/api.go index 066fe996eec..200fc187958 100644 --- a/storage/pipeline/mocks/api.go +++ b/storage/pipeline/mocks/api.go @@ -200,10 +200,10 @@ func (mr *MockSealingAPIMockRecorder) StateLookupID(arg0, arg1, arg2 interface{} } // StateMarketStorageDeal mocks base method. -func (m *MockSealingAPI) StateMarketStorageDeal(arg0 context.Context, arg1 abi.DealID, arg2 types.TipSetKey) (*api.MarketDeal, error) { +func (m *MockSealingAPI) StateMarketStorageDeal(arg0 context.Context, arg1 abi.DealID, arg2 types.TipSetKey) (*types.MarketDeal, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateMarketStorageDeal", arg0, arg1, arg2) - ret0, _ := ret[0].(*api.MarketDeal) + ret0, _ := ret[0].(*types.MarketDeal) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/storage/pipeline/sealing.go b/storage/pipeline/sealing.go index 6caa9ddc6c6..38374e810b3 100644 --- a/storage/pipeline/sealing.go +++ b/storage/pipeline/sealing.go @@ -58,7 +58,7 @@ type SealingAPI interface { StateMinerInfo(context.Context, address.Address, types.TipSetKey) (api.MinerInfo, error) StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (big.Int, error) StateMinerSectorAllocated(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (bool, error) - StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*api.MarketDeal, error) + StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*types.MarketDeal, error) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) ([]api.Deadline, error) diff --git a/storage/pipeline/states_failed_test.go b/storage/pipeline/states_failed_test.go index f6846c8f5f1..f6c293a7afe 100644 --- a/storage/pipeline/states_failed_test.go +++ b/storage/pipeline/states_failed_test.go @@ -50,7 +50,7 @@ func TestStateRecoverDealIDs(t *testing.T) { } //stm: @CHAIN_STATE_MARKET_STORAGE_DEAL_001, @CHAIN_STATE_NETWORK_VERSION_001 - api.EXPECT().StateMarketStorageDeal(ctx, dealId, nil).Return(&api2.MarketDeal{Proposal: dealProposal}, nil) + api.EXPECT().StateMarketStorageDeal(ctx, dealId, nil).Return(&types.MarketDeal{Proposal: dealProposal}, nil) pc := idCid("publishCID") @@ -65,7 +65,7 @@ func TestStateRecoverDealIDs(t *testing.T) { }, }, nil) api.EXPECT().StateNetworkVersion(ctx, nil).Return(network.Version0, nil) - api.EXPECT().StateMarketStorageDeal(ctx, dealId, nil).Return(&api2.MarketDeal{ + api.EXPECT().StateMarketStorageDeal(ctx, dealId, nil).Return(&types.MarketDeal{ Proposal: dealProposal, }, nil) From 3a997bfbe3e8a34bede656a1327ef6e5aec02505 Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Wed, 14 Dec 2022 00:55:17 -0500 Subject: [PATCH 5/8] Move BLockTemplate to chain/types --- api/api_full.go | 13 ------------- api/mocks/mock_full.go | 2 +- api/proxy_gen.go | 6 +++--- api/v0api/full.go | 2 +- api/v0api/proxy_gen.go | 6 +++--- api/v0api/v0mocks/mock_full.go | 2 +- build/openrpc/full.json.gz | Bin 31090 -> 31090 bytes chain/consensus/filcns/mine.go | 3 +-- chain/consensus/iface.go | 3 +-- chain/gen/gen.go | 3 +-- chain/types/blocktemplate.go | 20 ++++++++++++++++++++ cmd/lotus/debug_advance.go | 3 +-- miner/miner.go | 3 +-- node/impl/full/state.go | 2 +- 14 files changed, 35 insertions(+), 33 deletions(-) create mode 100644 chain/types/blocktemplate.go diff --git a/api/api_full.go b/api/api_full.go index b1dc2da0f23..4d138014da2 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -26,7 +26,6 @@ import ( abinetwork "github.com/filecoin-project/go-state-types/network" apitypes "github.com/filecoin-project/lotus/api/types" - "github.com/filecoin-project/lotus/chain/actors/builtin" lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/builtin/power" "github.com/filecoin-project/lotus/chain/store" @@ -1149,18 +1148,6 @@ type DealCollateralBounds struct { Max abi.TokenAmount } -type BlockTemplate struct { - Miner address.Address - Parents types.TipSetKey - Ticket *types.Ticket - Eproof *types.ElectionProof - BeaconValues []types.BeaconEntry - Messages []*types.SignedMessage - Epoch abi.ChainEpoch - Timestamp uint64 - WinningPoStProof []builtin.PoStProof -} - type DataSize struct { PayloadSize int64 PieceSize abi.PaddedPieceSize diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 7119ce4ec0b..7945d873c43 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -1446,7 +1446,7 @@ func (mr *MockFullNodeMockRecorder) MarketWithdraw(arg0, arg1, arg2, arg3 interf } // MinerCreateBlock mocks base method. -func (m *MockFullNode) MinerCreateBlock(arg0 context.Context, arg1 *api.BlockTemplate) (*types.BlockMsg, error) { +func (m *MockFullNode) MinerCreateBlock(arg0 context.Context, arg1 *types.BlockTemplate) (*types.BlockMsg, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "MinerCreateBlock", arg0, arg1) ret0, _ := ret[0].(*types.BlockMsg) diff --git a/api/proxy_gen.go b/api/proxy_gen.go index ad31757234e..f572f9deca8 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -282,7 +282,7 @@ type FullNodeStruct struct { MarketWithdraw func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` - MinerCreateBlock func(p0 context.Context, p1 *BlockTemplate) (*types.BlockMsg, error) `perm:"write"` + MinerCreateBlock func(p0 context.Context, p1 *types.BlockTemplate) (*types.BlockMsg, error) `perm:"write"` MinerGetBaseInfo func(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*types.MiningBaseInfo, error) `perm:"read"` @@ -2186,14 +2186,14 @@ func (s *FullNodeStub) MarketWithdraw(p0 context.Context, p1 address.Address, p2 return *new(cid.Cid), ErrNotSupported } -func (s *FullNodeStruct) MinerCreateBlock(p0 context.Context, p1 *BlockTemplate) (*types.BlockMsg, error) { +func (s *FullNodeStruct) MinerCreateBlock(p0 context.Context, p1 *types.BlockTemplate) (*types.BlockMsg, error) { if s.Internal.MinerCreateBlock == nil { return nil, ErrNotSupported } return s.Internal.MinerCreateBlock(p0, p1) } -func (s *FullNodeStub) MinerCreateBlock(p0 context.Context, p1 *BlockTemplate) (*types.BlockMsg, error) { +func (s *FullNodeStub) MinerCreateBlock(p0 context.Context, p1 *types.BlockTemplate) (*types.BlockMsg, error) { return nil, ErrNotSupported } diff --git a/api/v0api/full.go b/api/v0api/full.go index f2a0961d209..95f6de02509 100644 --- a/api/v0api/full.go +++ b/api/v0api/full.go @@ -270,7 +270,7 @@ type FullNode interface { // MethodGroup: Miner MinerGetBaseInfo(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*types.MiningBaseInfo, error) //perm:read - MinerCreateBlock(context.Context, *api.BlockTemplate) (*types.BlockMsg, error) //perm:write + MinerCreateBlock(context.Context, *types.BlockTemplate) (*types.BlockMsg, error) //perm:write // // UX ? diff --git a/api/v0api/proxy_gen.go b/api/v0api/proxy_gen.go index 6497db3487a..acc707cfd35 100644 --- a/api/v0api/proxy_gen.go +++ b/api/v0api/proxy_gen.go @@ -163,7 +163,7 @@ type FullNodeStruct struct { MarketWithdraw func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` - MinerCreateBlock func(p0 context.Context, p1 *api.BlockTemplate) (*types.BlockMsg, error) `perm:"write"` + MinerCreateBlock func(p0 context.Context, p1 *types.BlockTemplate) (*types.BlockMsg, error) `perm:"write"` MinerGetBaseInfo func(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*types.MiningBaseInfo, error) `perm:"read"` @@ -1167,14 +1167,14 @@ func (s *FullNodeStub) MarketWithdraw(p0 context.Context, p1 address.Address, p2 return *new(cid.Cid), ErrNotSupported } -func (s *FullNodeStruct) MinerCreateBlock(p0 context.Context, p1 *api.BlockTemplate) (*types.BlockMsg, error) { +func (s *FullNodeStruct) MinerCreateBlock(p0 context.Context, p1 *types.BlockTemplate) (*types.BlockMsg, error) { if s.Internal.MinerCreateBlock == nil { return nil, ErrNotSupported } return s.Internal.MinerCreateBlock(p0, p1) } -func (s *FullNodeStub) MinerCreateBlock(p0 context.Context, p1 *api.BlockTemplate) (*types.BlockMsg, error) { +func (s *FullNodeStub) MinerCreateBlock(p0 context.Context, p1 *types.BlockTemplate) (*types.BlockMsg, error) { return nil, ErrNotSupported } diff --git a/api/v0api/v0mocks/mock_full.go b/api/v0api/v0mocks/mock_full.go index 0316b16509c..d20db13fd9c 100644 --- a/api/v0api/v0mocks/mock_full.go +++ b/api/v0api/v0mocks/mock_full.go @@ -1091,7 +1091,7 @@ func (mr *MockFullNodeMockRecorder) MarketWithdraw(arg0, arg1, arg2, arg3 interf } // MinerCreateBlock mocks base method. -func (m *MockFullNode) MinerCreateBlock(arg0 context.Context, arg1 *api.BlockTemplate) (*types.BlockMsg, error) { +func (m *MockFullNode) MinerCreateBlock(arg0 context.Context, arg1 *types.BlockTemplate) (*types.BlockMsg, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "MinerCreateBlock", arg0, arg1) ret0, _ := ret[0].(*types.BlockMsg) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 915e0443bf227411ed93d2b3c79e3f62e898fe43..21f5df28be1b7423d882bf1cd56c7b94a8f19933 100644 GIT binary patch delta 20144 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�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 diff --git a/chain/consensus/filcns/mine.go b/chain/consensus/filcns/mine.go index 0c80161cc3f..0930d8b974c 100644 --- a/chain/consensus/filcns/mine.go +++ b/chain/consensus/filcns/mine.go @@ -8,13 +8,12 @@ import ( "github.com/filecoin-project/go-state-types/crypto" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/consensus" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" ) -func (filec *FilecoinEC) CreateBlock(ctx context.Context, w types.Signer, bt *api.BlockTemplate) (*types.FullBlock, error) { +func (filec *FilecoinEC) CreateBlock(ctx context.Context, w types.Signer, bt *types.BlockTemplate) (*types.FullBlock, error) { pts, err := filec.sm.ChainStore().LoadTipSet(ctx, bt.Parents) if err != nil { return nil, xerrors.Errorf("failed to load parent tipset: %w", err) diff --git a/chain/consensus/iface.go b/chain/consensus/iface.go index a75aba336fd..386d083a1c6 100644 --- a/chain/consensus/iface.go +++ b/chain/consensus/iface.go @@ -7,7 +7,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" ) @@ -16,5 +15,5 @@ type Consensus interface { ValidateBlockPubsub(ctx context.Context, self bool, msg *pubsub.Message) (pubsub.ValidationResult, string) IsEpochBeyondCurrMax(epoch abi.ChainEpoch) bool - CreateBlock(ctx context.Context, s types.Signer, bt *api.BlockTemplate) (*types.FullBlock, error) + CreateBlock(ctx context.Context, s types.Signer, bt *types.BlockTemplate) (*types.FullBlock, error) } diff --git a/chain/gen/gen.go b/chain/gen/gen.go index b44855434bf..32ce06a5a03 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -26,7 +26,6 @@ import ( "github.com/filecoin-project/go-state-types/network" proof7 "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/policy" @@ -498,7 +497,7 @@ func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, vrfticke ts = parents.MinTimestamp() + uint64(height-parents.Height())*build.BlockDelaySecs } - fblk, err := filcns.NewFilecoinExpectedConsensus(cg.sm, nil, nil, nil).CreateBlock(context.TODO(), cg.w, &api.BlockTemplate{ + fblk, err := filcns.NewFilecoinExpectedConsensus(cg.sm, nil, nil, nil).CreateBlock(context.TODO(), cg.w, &types.BlockTemplate{ Miner: m, Parents: parents.Key(), Ticket: vrfticket, diff --git a/chain/types/blocktemplate.go b/chain/types/blocktemplate.go new file mode 100644 index 00000000000..8ff810fb66f --- /dev/null +++ b/chain/types/blocktemplate.go @@ -0,0 +1,20 @@ +package types + +import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/chain/actors/builtin" +) + +type BlockTemplate struct { + Miner address.Address + Parents TipSetKey + Ticket *Ticket + Eproof *ElectionProof + BeaconValues []BeaconEntry + Messages []*SignedMessage + Epoch abi.ChainEpoch + Timestamp uint64 + WinningPoStProof []builtin.PoStProof +} diff --git a/cmd/lotus/debug_advance.go b/cmd/lotus/debug_advance.go index dee2db97e2b..374fa36e452 100644 --- a/cmd/lotus/debug_advance.go +++ b/cmd/lotus/debug_advance.go @@ -13,7 +13,6 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/crypto" - lapi "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/types" @@ -82,7 +81,7 @@ func init() { uts := head.MinTimestamp() + uint64(build.BlockDelaySecs) nheight := head.Height() + 1 - blk, err := api.MinerCreateBlock(ctx, &lapi.BlockTemplate{ + blk, err := api.MinerCreateBlock(ctx, &types.BlockTemplate{ addr, head.Key(), ticket, ep, mbi.BeaconEntries, msgs, nheight, uts, gen.ValidWpostForTesting, }) if err != nil { diff --git a/miner/miner.go b/miner/miner.go index c9ed20813b1..7c3ce1fde37 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -21,7 +21,6 @@ import ( "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/proof" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api/v1api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -616,7 +615,7 @@ func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *type nheight := base.TipSet.Height() + base.NullRounds + 1 // why even return this? that api call could just submit it for us - return m.api.MinerCreateBlock(context.TODO(), &api.BlockTemplate{ + return m.api.MinerCreateBlock(context.TODO(), &types.BlockTemplate{ Miner: addr, Parents: base.TipSet.Key(), Ticket: ticket, diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 5cbea717756..fafc72d1a4d 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -580,7 +580,7 @@ func (a *StateAPI) MinerGetBaseInfo(ctx context.Context, maddr address.Address, return stmgr.MinerGetBaseInfo(ctx, a.StateManager, a.Beacon, tsk, epoch, maddr, a.ProofVerifier) } -func (a *StateAPI) MinerCreateBlock(ctx context.Context, bt *api.BlockTemplate) (*types.BlockMsg, error) { +func (a *StateAPI) MinerCreateBlock(ctx context.Context, bt *types.BlockTemplate) (*types.BlockMsg, error) { fblk, err := a.Consensus.CreateBlock(ctx, a.Wallet, bt) if err != nil { return nil, err From cf677ae09f64bf4df21152ff489137741bed6cd4 Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Wed, 14 Dec 2022 00:58:11 -0500 Subject: [PATCH 6/8] Move MsgLookup to chain/types --- api/api_full.go | 12 ++------ api/api_gateway.go | 4 +-- api/eth_types.go | 2 +- api/mocks/mock_full.go | 8 ++--- api/proxy_gen.go | 24 +++++++-------- api/v0api/full.go | 8 ++--- api/v0api/gateway.go | 4 +-- api/v0api/proxy_gen.go | 36 +++++++++++------------ api/v0api/v0mocks/mock_full.go | 16 +++++----- api/v0api/v1_wrapper.go | 8 ++--- build/openrpc/full.json.gz | Bin 31090 -> 31091 bytes build/openrpc/gateway.json.gz | Bin 4989 -> 4991 bytes chain/events/cache.go | 3 +- chain/events/events.go | 2 +- chain/events/events_test.go | 2 +- chain/market/fundmanager.go | 2 +- chain/market/fundmanager_test.go | 4 +-- chain/types/message.go | 8 +++++ cli/state.go | 2 +- cli/wallet_test.go | 3 +- gateway/node.go | 8 ++--- gateway/node_test.go | 2 +- itests/kit/evm.go | 3 +- itests/paych_api_test.go | 2 +- itests/splitstore_test.go | 2 +- node/impl/full/eth.go | 2 +- node/impl/full/state.go | 12 ++++---- paychmgr/manager.go | 2 +- paychmgr/mock_test.go | 6 ++-- paychmgr/settler/settler.go | 2 +- storage/pipeline/currentdealinfo.go | 2 +- storage/pipeline/currentdealinfo_test.go | 27 ++++++++--------- storage/pipeline/mocks/api.go | 8 ++--- storage/pipeline/sealing.go | 4 +-- storage/pipeline/states_failed_test.go | 2 +- storage/wdpost/wdpost_run_test.go | 4 +-- storage/wdpost/wdpost_sched.go | 2 +- 37 files changed, 117 insertions(+), 121 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 4d138014da2..6954f06fe7a 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -496,7 +496,7 @@ type FullNode interface { // A replacing message is a message with a different CID, any of Gas values, and // different signature, but with all other parameters matching (source/destination, // nonce, params, etc.) - StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*MsgLookup, error) //perm:read + StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*types.MsgLookup, error) //perm:read // StateWaitMsg looks back up to limit epochs in the chain for a message. // If not found, it blocks until the message arrives on chain, and gets to the // indicated confidence depth. @@ -515,7 +515,7 @@ type FullNode interface { // A replacing message is a message with a different CID, any of Gas values, and // different signature, but with all other parameters matching (source/destination, // nonce, params, etc.) - StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*MsgLookup, error) //perm:read + StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*types.MsgLookup, error) //perm:read // StateListMiners returns the addresses of every miner that has claimed power in the Power Actor StateListMiners(context.Context, types.TipSetKey) ([]address.Address, error) //perm:read // StateListActors returns the addresses of every actor in the state @@ -873,14 +873,6 @@ type DealInfo struct { DataTransfer *DataTransferChannel } -type MsgLookup struct { - Message cid.Cid // Can be different than requested, in case it was replaced, but only gas values changed - Receipt types.MessageReceipt - ReturnDec interface{} - TipSet types.TipSetKey - Height abi.ChainEpoch -} - // BlsMessages[x].cid = Cids[x] // SecpkMessages[y].cid = Cids[BlsMessages.length + y] type BlockMessages struct { diff --git a/api/api_gateway.go b/api/api_gateway.go index 4a6d78c87d8..9d14e083ce2 100644 --- a/api/api_gateway.go +++ b/api/api_gateway.go @@ -65,8 +65,8 @@ type Gateway interface { StateNetworkVersion(context.Context, types.TipSetKey) (apitypes.NetworkVersion, error) StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) - StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*MsgLookup, error) - StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*MsgLookup, error) + StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*types.MsgLookup, error) + StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*types.MsgLookup, error) WalletBalance(context.Context, address.Address) (types.BigInt, error) Version(context.Context) (APIVersion, error) Discover(context.Context) (apitypes.OpenRPCDocument, error) diff --git a/api/eth_types.go b/api/eth_types.go index c5de37bd80a..1a8f38cc33a 100644 --- a/api/eth_types.go +++ b/api/eth_types.go @@ -199,7 +199,7 @@ type EthTxReceipt struct { Logs []string `json:"logs"` } -func NewEthTxReceipt(tx EthTx, lookup *MsgLookup, replay *types.InvocResult) (EthTxReceipt, error) { +func NewEthTxReceipt(tx EthTx, lookup *types.MsgLookup, replay *types.InvocResult) (EthTxReceipt, error) { receipt := EthTxReceipt{ TransactionHash: tx.Hash, TransactionIndex: tx.TransactionIndex, diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 7945d873c43..809a891ed7f 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -3430,10 +3430,10 @@ func (mr *MockFullNodeMockRecorder) StateReplay(arg0, arg1, arg2 interface{}) *g } // StateSearchMsg mocks base method. -func (m *MockFullNode) StateSearchMsg(arg0 context.Context, arg1 types.TipSetKey, arg2 cid.Cid, arg3 abi.ChainEpoch, arg4 bool) (*api.MsgLookup, error) { +func (m *MockFullNode) StateSearchMsg(arg0 context.Context, arg1 types.TipSetKey, arg2 cid.Cid, arg3 abi.ChainEpoch, arg4 bool) (*types.MsgLookup, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateSearchMsg", arg0, arg1, arg2, arg3, arg4) - ret0, _ := ret[0].(*api.MsgLookup) + ret0, _ := ret[0].(*types.MsgLookup) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -3565,10 +3565,10 @@ func (mr *MockFullNodeMockRecorder) StateVerifierStatus(arg0, arg1, arg2 interfa } // StateWaitMsg mocks base method. -func (m *MockFullNode) StateWaitMsg(arg0 context.Context, arg1 cid.Cid, arg2 uint64, arg3 abi.ChainEpoch, arg4 bool) (*api.MsgLookup, error) { +func (m *MockFullNode) StateWaitMsg(arg0 context.Context, arg1 cid.Cid, arg2 uint64, arg3 abi.ChainEpoch, arg4 bool) (*types.MsgLookup, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateWaitMsg", arg0, arg1, arg2, arg3, arg4) - ret0, _ := ret[0].(*api.MsgLookup) + ret0, _ := ret[0].(*types.MsgLookup) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/api/proxy_gen.go b/api/proxy_gen.go index f572f9deca8..0902073d315 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -496,7 +496,7 @@ type FullNodeStruct struct { StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*types.InvocResult, error) `perm:"read"` - StateSearchMsg func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `perm:"read"` + StateSearchMsg func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*types.MsgLookup, error) `perm:"read"` StateSectorExpiration func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorExpiration, error) `perm:"read"` @@ -514,7 +514,7 @@ type FullNodeStruct struct { StateVerifierStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` - StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `perm:"read"` + StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*types.MsgLookup, error) `perm:"read"` SyncCheckBad func(p0 context.Context, p1 cid.Cid) (string, error) `perm:"read"` @@ -636,13 +636,13 @@ type GatewayStruct struct { StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*ActorState, error) `perm:"read"` - StateSearchMsg func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `` + StateSearchMsg func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*types.MsgLookup, error) `` StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `` StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `` - StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `` + StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*types.MsgLookup, error) `` Version func(p0 context.Context) (APIVersion, error) `` @@ -3363,14 +3363,14 @@ func (s *FullNodeStub) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 ci return nil, ErrNotSupported } -func (s *FullNodeStruct) StateSearchMsg(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) { +func (s *FullNodeStruct) StateSearchMsg(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*types.MsgLookup, error) { if s.Internal.StateSearchMsg == nil { return nil, ErrNotSupported } return s.Internal.StateSearchMsg(p0, p1, p2, p3, p4) } -func (s *FullNodeStub) StateSearchMsg(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) { +func (s *FullNodeStub) StateSearchMsg(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*types.MsgLookup, error) { return nil, ErrNotSupported } @@ -3462,14 +3462,14 @@ func (s *FullNodeStub) StateVerifierStatus(p0 context.Context, p1 address.Addres return nil, ErrNotSupported } -func (s *FullNodeStruct) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) { +func (s *FullNodeStruct) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*types.MsgLookup, error) { if s.Internal.StateWaitMsg == nil { return nil, ErrNotSupported } return s.Internal.StateWaitMsg(p0, p1, p2, p3, p4) } -func (s *FullNodeStub) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) { +func (s *FullNodeStub) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*types.MsgLookup, error) { return nil, ErrNotSupported } @@ -4078,14 +4078,14 @@ func (s *GatewayStub) StateReadState(p0 context.Context, p1 address.Address, p2 return nil, ErrNotSupported } -func (s *GatewayStruct) StateSearchMsg(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) { +func (s *GatewayStruct) StateSearchMsg(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*types.MsgLookup, error) { if s.Internal.StateSearchMsg == nil { return nil, ErrNotSupported } return s.Internal.StateSearchMsg(p0, p1, p2, p3, p4) } -func (s *GatewayStub) StateSearchMsg(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) { +func (s *GatewayStub) StateSearchMsg(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*types.MsgLookup, error) { return nil, ErrNotSupported } @@ -4111,14 +4111,14 @@ func (s *GatewayStub) StateVerifiedClientStatus(p0 context.Context, p1 address.A return nil, ErrNotSupported } -func (s *GatewayStruct) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) { +func (s *GatewayStruct) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*types.MsgLookup, error) { if s.Internal.StateWaitMsg == nil { return nil, ErrNotSupported } return s.Internal.StateWaitMsg(p0, p1, p2, p3, p4) } -func (s *GatewayStub) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) { +func (s *GatewayStub) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*types.MsgLookup, error) { return nil, ErrNotSupported } diff --git a/api/v0api/full.go b/api/v0api/full.go index 95f6de02509..c1fb641427e 100644 --- a/api/v0api/full.go +++ b/api/v0api/full.go @@ -469,7 +469,7 @@ type FullNode interface { // A replacing message is a message with a different CID, any of Gas values, and // different signature, but with all other parameters matching (source/destination, // nonce, params, etc.) - StateSearchMsg(context.Context, cid.Cid) (*api.MsgLookup, error) //perm:read + StateSearchMsg(context.Context, cid.Cid) (*types.MsgLookup, error) //perm:read // StateSearchMsgLimited looks back up to limit epochs in the chain for a message, and returns its receipt and the tipset where it was executed // // NOTE: If a replacing message is found on chain, this method will return @@ -485,7 +485,7 @@ type FullNode interface { // A replacing message is a message with a different CID, any of Gas values, and // different signature, but with all other parameters matching (source/destination, // nonce, params, etc.) - StateSearchMsgLimited(ctx context.Context, msg cid.Cid, limit abi.ChainEpoch) (*api.MsgLookup, error) //perm:read + StateSearchMsgLimited(ctx context.Context, msg cid.Cid, limit abi.ChainEpoch) (*types.MsgLookup, error) //perm:read // StateWaitMsg looks back in the chain for a message. If not found, it blocks until the // message arrives on chain, and gets to the indicated confidence depth. // @@ -502,7 +502,7 @@ type FullNode interface { // A replacing message is a message with a different CID, any of Gas values, and // different signature, but with all other parameters matching (source/destination, // nonce, params, etc.) - StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error) //perm:read + StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*types.MsgLookup, error) //perm:read // StateWaitMsgLimited looks back up to limit epochs in the chain for a message. // If not found, it blocks until the message arrives on chain, and gets to the // indicated confidence depth. @@ -520,7 +520,7 @@ type FullNode interface { // A replacing message is a message with a different CID, any of Gas values, and // different signature, but with all other parameters matching (source/destination, // nonce, params, etc.) - StateWaitMsgLimited(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch) (*api.MsgLookup, error) //perm:read + StateWaitMsgLimited(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch) (*types.MsgLookup, error) //perm:read // StateListMiners returns the addresses of every miner that has claimed power in the Power Actor StateListMiners(context.Context, types.TipSetKey) ([]address.Address, error) //perm:read // StateListActors returns the addresses of every actor in the state diff --git a/api/v0api/gateway.go b/api/v0api/gateway.go index 887355efc54..db38bdd97dd 100644 --- a/api/v0api/gateway.go +++ b/api/v0api/gateway.go @@ -61,10 +61,10 @@ type Gateway interface { StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) StateNetworkVersion(context.Context, types.TipSetKey) (abinetwork.Version, error) - StateSearchMsg(ctx context.Context, msg cid.Cid) (*api.MsgLookup, error) + StateSearchMsg(ctx context.Context, msg cid.Cid) (*types.MsgLookup, error) StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) - StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) + StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*types.MsgLookup, error) WalletBalance(context.Context, address.Address) (types.BigInt, error) Version(context.Context) (api.APIVersion, error) } diff --git a/api/v0api/proxy_gen.go b/api/v0api/proxy_gen.go index acc707cfd35..d2406898c14 100644 --- a/api/v0api/proxy_gen.go +++ b/api/v0api/proxy_gen.go @@ -349,9 +349,9 @@ type FullNodeStruct struct { StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*types.InvocResult, error) `perm:"read"` - StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) `perm:"read"` + StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*types.MsgLookup, error) `perm:"read"` - StateSearchMsgLimited func(p0 context.Context, p1 cid.Cid, p2 abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"` + StateSearchMsgLimited func(p0 context.Context, p1 cid.Cid, p2 abi.ChainEpoch) (*types.MsgLookup, error) `perm:"read"` StateSectorExpiration func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorExpiration, error) `perm:"read"` @@ -369,9 +369,9 @@ type FullNodeStruct struct { StateVerifierStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` - StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64) (*api.MsgLookup, error) `perm:"read"` + StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64) (*types.MsgLookup, error) `perm:"read"` - StateWaitMsgLimited func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"` + StateWaitMsgLimited func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch) (*types.MsgLookup, error) `perm:"read"` SyncCheckBad func(p0 context.Context, p1 cid.Cid) (string, error) `perm:"read"` @@ -479,13 +479,13 @@ type GatewayStruct struct { StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (abinetwork.Version, error) `` - StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) `` + StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*types.MsgLookup, error) `` StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `` StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `` - StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64) (*api.MsgLookup, error) `` + StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64) (*types.MsgLookup, error) `` Version func(p0 context.Context) (api.APIVersion, error) `` @@ -2190,25 +2190,25 @@ func (s *FullNodeStub) StateReplay(p0 context.Context, p1 types.TipSetKey, p2 ci return nil, ErrNotSupported } -func (s *FullNodeStruct) StateSearchMsg(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) { +func (s *FullNodeStruct) StateSearchMsg(p0 context.Context, p1 cid.Cid) (*types.MsgLookup, error) { if s.Internal.StateSearchMsg == nil { return nil, ErrNotSupported } return s.Internal.StateSearchMsg(p0, p1) } -func (s *FullNodeStub) StateSearchMsg(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) { +func (s *FullNodeStub) StateSearchMsg(p0 context.Context, p1 cid.Cid) (*types.MsgLookup, error) { return nil, ErrNotSupported } -func (s *FullNodeStruct) StateSearchMsgLimited(p0 context.Context, p1 cid.Cid, p2 abi.ChainEpoch) (*api.MsgLookup, error) { +func (s *FullNodeStruct) StateSearchMsgLimited(p0 context.Context, p1 cid.Cid, p2 abi.ChainEpoch) (*types.MsgLookup, error) { if s.Internal.StateSearchMsgLimited == nil { return nil, ErrNotSupported } return s.Internal.StateSearchMsgLimited(p0, p1, p2) } -func (s *FullNodeStub) StateSearchMsgLimited(p0 context.Context, p1 cid.Cid, p2 abi.ChainEpoch) (*api.MsgLookup, error) { +func (s *FullNodeStub) StateSearchMsgLimited(p0 context.Context, p1 cid.Cid, p2 abi.ChainEpoch) (*types.MsgLookup, error) { return nil, ErrNotSupported } @@ -2300,25 +2300,25 @@ func (s *FullNodeStub) StateVerifierStatus(p0 context.Context, p1 address.Addres return nil, ErrNotSupported } -func (s *FullNodeStruct) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64) (*api.MsgLookup, error) { +func (s *FullNodeStruct) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64) (*types.MsgLookup, error) { if s.Internal.StateWaitMsg == nil { return nil, ErrNotSupported } return s.Internal.StateWaitMsg(p0, p1, p2) } -func (s *FullNodeStub) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64) (*api.MsgLookup, error) { +func (s *FullNodeStub) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64) (*types.MsgLookup, error) { return nil, ErrNotSupported } -func (s *FullNodeStruct) StateWaitMsgLimited(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch) (*api.MsgLookup, error) { +func (s *FullNodeStruct) StateWaitMsgLimited(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch) (*types.MsgLookup, error) { if s.Internal.StateWaitMsgLimited == nil { return nil, ErrNotSupported } return s.Internal.StateWaitMsgLimited(p0, p1, p2, p3) } -func (s *FullNodeStub) StateWaitMsgLimited(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch) (*api.MsgLookup, error) { +func (s *FullNodeStub) StateWaitMsgLimited(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch) (*types.MsgLookup, error) { return nil, ErrNotSupported } @@ -2850,14 +2850,14 @@ func (s *GatewayStub) StateNetworkVersion(p0 context.Context, p1 types.TipSetKey return *new(abinetwork.Version), ErrNotSupported } -func (s *GatewayStruct) StateSearchMsg(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) { +func (s *GatewayStruct) StateSearchMsg(p0 context.Context, p1 cid.Cid) (*types.MsgLookup, error) { if s.Internal.StateSearchMsg == nil { return nil, ErrNotSupported } return s.Internal.StateSearchMsg(p0, p1) } -func (s *GatewayStub) StateSearchMsg(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) { +func (s *GatewayStub) StateSearchMsg(p0 context.Context, p1 cid.Cid) (*types.MsgLookup, error) { return nil, ErrNotSupported } @@ -2883,14 +2883,14 @@ func (s *GatewayStub) StateVerifiedClientStatus(p0 context.Context, p1 address.A return nil, ErrNotSupported } -func (s *GatewayStruct) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64) (*api.MsgLookup, error) { +func (s *GatewayStruct) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64) (*types.MsgLookup, error) { if s.Internal.StateWaitMsg == nil { return nil, ErrNotSupported } return s.Internal.StateWaitMsg(p0, p1, p2) } -func (s *GatewayStub) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64) (*api.MsgLookup, error) { +func (s *GatewayStub) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64) (*types.MsgLookup, error) { return nil, ErrNotSupported } diff --git a/api/v0api/v0mocks/mock_full.go b/api/v0api/v0mocks/mock_full.go index d20db13fd9c..4e79a5dbaec 100644 --- a/api/v0api/v0mocks/mock_full.go +++ b/api/v0api/v0mocks/mock_full.go @@ -2865,10 +2865,10 @@ func (mr *MockFullNodeMockRecorder) StateReplay(arg0, arg1, arg2 interface{}) *g } // StateSearchMsg mocks base method. -func (m *MockFullNode) StateSearchMsg(arg0 context.Context, arg1 cid.Cid) (*api.MsgLookup, error) { +func (m *MockFullNode) StateSearchMsg(arg0 context.Context, arg1 cid.Cid) (*types.MsgLookup, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateSearchMsg", arg0, arg1) - ret0, _ := ret[0].(*api.MsgLookup) + ret0, _ := ret[0].(*types.MsgLookup) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -2880,10 +2880,10 @@ func (mr *MockFullNodeMockRecorder) StateSearchMsg(arg0, arg1 interface{}) *gomo } // StateSearchMsgLimited mocks base method. -func (m *MockFullNode) StateSearchMsgLimited(arg0 context.Context, arg1 cid.Cid, arg2 abi.ChainEpoch) (*api.MsgLookup, error) { +func (m *MockFullNode) StateSearchMsgLimited(arg0 context.Context, arg1 cid.Cid, arg2 abi.ChainEpoch) (*types.MsgLookup, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateSearchMsgLimited", arg0, arg1, arg2) - ret0, _ := ret[0].(*api.MsgLookup) + ret0, _ := ret[0].(*types.MsgLookup) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -3015,10 +3015,10 @@ func (mr *MockFullNodeMockRecorder) StateVerifierStatus(arg0, arg1, arg2 interfa } // StateWaitMsg mocks base method. -func (m *MockFullNode) StateWaitMsg(arg0 context.Context, arg1 cid.Cid, arg2 uint64) (*api.MsgLookup, error) { +func (m *MockFullNode) StateWaitMsg(arg0 context.Context, arg1 cid.Cid, arg2 uint64) (*types.MsgLookup, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateWaitMsg", arg0, arg1, arg2) - ret0, _ := ret[0].(*api.MsgLookup) + ret0, _ := ret[0].(*types.MsgLookup) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -3030,10 +3030,10 @@ func (mr *MockFullNodeMockRecorder) StateWaitMsg(arg0, arg1, arg2 interface{}) * } // StateWaitMsgLimited mocks base method. -func (m *MockFullNode) StateWaitMsgLimited(arg0 context.Context, arg1 cid.Cid, arg2 uint64, arg3 abi.ChainEpoch) (*api.MsgLookup, error) { +func (m *MockFullNode) StateWaitMsgLimited(arg0 context.Context, arg1 cid.Cid, arg2 uint64, arg3 abi.ChainEpoch) (*types.MsgLookup, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateWaitMsgLimited", arg0, arg1, arg2, arg3) - ret0, _ := ret[0].(*api.MsgLookup) + ret0, _ := ret[0].(*types.MsgLookup) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/api/v0api/v1_wrapper.go b/api/v0api/v1_wrapper.go index f58b0420f32..e85d4387f6e 100644 --- a/api/v0api/v1_wrapper.go +++ b/api/v0api/v1_wrapper.go @@ -37,19 +37,19 @@ func (w *WrapperV1Full) StateSectorPreCommitInfo(ctx context.Context, maddr addr return *pi, nil } -func (w *WrapperV1Full) StateSearchMsg(ctx context.Context, msg cid.Cid) (*api.MsgLookup, error) { +func (w *WrapperV1Full) StateSearchMsg(ctx context.Context, msg cid.Cid) (*types.MsgLookup, error) { return w.FullNode.StateSearchMsg(ctx, types.EmptyTSK, msg, api.LookbackNoLimit, true) } -func (w *WrapperV1Full) StateSearchMsgLimited(ctx context.Context, msg cid.Cid, limit abi.ChainEpoch) (*api.MsgLookup, error) { +func (w *WrapperV1Full) StateSearchMsgLimited(ctx context.Context, msg cid.Cid, limit abi.ChainEpoch) (*types.MsgLookup, error) { return w.FullNode.StateSearchMsg(ctx, types.EmptyTSK, msg, limit, true) } -func (w *WrapperV1Full) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) { +func (w *WrapperV1Full) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*types.MsgLookup, error) { return w.FullNode.StateWaitMsg(ctx, msg, confidence, api.LookbackNoLimit, true) } -func (w *WrapperV1Full) StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, limit abi.ChainEpoch) (*api.MsgLookup, error) { +func (w *WrapperV1Full) StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, limit abi.ChainEpoch) (*types.MsgLookup, error) { return w.FullNode.StateWaitMsg(ctx, msg, confidence, limit, true) } diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 21f5df28be1b7423d882bf1cd56c7b94a8f19933..573dce338ac57a1925a1076dfafd451b11b8920a 100644 GIT binary patch delta 4880 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 C!gMJB delta 4879 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 TSNH!P00960Ftk{C&G7&L)FN|) delta 735 zcmV<50wDeWCjBO`s}O%H*voOJ{P5&bOpkl9K1>$}CT70!d)Szan-8v)8mYON?N8p! zR+WS-4F?aH$F1AxuHlHs;14BoE8YN%@Ume4Pk5zxbL)Dng$pnMJB){IVa9cN$A9jl zZ}AN-C&>NED<2^x^lbmi`g&bjCv0sOrXHSXY1UDwdcnYF3Cae5C-l zh*OfcpMI4NCX4u9E6A&8Q&RXoO14(=Az${v#dlSidw6uz39#Bh>nREydBgjU=o3e1;q&P#=e7xiI%HfqTTn`pOY!|4(2yzHdN8+ZjJn#=n#pxEtHC5iin zFsr-664rk$gT7=hrKfqAu${sBwpGHW*N1q?ST=b}rP&?WjNO4euyX-_Ft5X49a*26 zJ&k5hquJAF_B5J3jc&Ij8Dq^T@$z8fgpN{taniTPwq%N6GZ{pV z$EjB`uo;z(riylhED!XSNGZrb65Qbm7FwvE2N73E$;@=IEy)B~G4YaV|4gP_uO#o) zH)L70(^RJ_OZs45Yp Date: Wed, 14 Dec 2022 01:08:31 -0500 Subject: [PATCH 7/8] Move two structs to chain/types to remove api dependency on ffi --- api/api_full.go | 43 ++------------------- api/api_gateway.go | 5 +-- api/docgen/docgen.go | 3 +- api/mocks/mock_full.go | 9 ++--- api/proxy_gen.go | 33 ++++++++-------- api/v0api/full.go | 5 +-- api/v0api/gateway.go | 3 +- api/v0api/proxy_gen.go | 23 ++++++----- api/v0api/v0mocks/mock_full.go | 9 ++--- build/openrpc/full.json.gz | Bin 31091 -> 31089 bytes build/openrpc/gateway.json.gz | Bin 4991 -> 4981 bytes build/openrpc/miner.json.gz | Bin 15763 -> 15761 bytes build/openrpc/worker.json.gz | Bin 5278 -> 5278 bytes chain/events/cache.go | 5 +-- chain/events/events.go | 5 +-- chain/events/events_test.go | 22 +++++------ chain/events/observer.go | 4 +- chain/store/store.go | 27 ++++++------- chain/sync.go | 11 +++--- chain/sync_test.go | 2 +- chain/syncstate.go | 11 +++--- chain/types/head_change.go | 6 +++ chain/types/mining_base_info.go | 1 + chain/types/sync_state_stage.go | 36 +++++++++++++++++ cli/sync.go | 7 ++-- cli/sync_test.go | 2 +- cmd/lotus-shed/balancer.go | 2 +- gateway/node.go | 9 ++--- itests/api_test.go | 3 +- markets/utils/converters.go | 3 +- node/health.go | 4 +- node/impl/full/chain.go | 10 ++--- storage/wdpost/wdpost_sched.go | 4 +- tools/stats/headbuffer/head_buffer.go | 6 +-- tools/stats/headbuffer/head_buffer_test.go | 34 ++++++++-------- tools/stats/sync/sync.go | 6 +-- 36 files changed, 172 insertions(+), 181 deletions(-) create mode 100644 chain/types/head_change.go create mode 100644 chain/types/sync_state_stage.go diff --git a/api/api_full.go b/api/api_full.go index 6954f06fe7a..7d88d64eb50 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -3,7 +3,6 @@ package api import ( "context" "encoding/json" - "fmt" "time" "github.com/google/uuid" @@ -28,7 +27,6 @@ import ( apitypes "github.com/filecoin-project/lotus/api/types" lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/builtin/power" - "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/repo/imports" @@ -70,7 +68,7 @@ type FullNode interface { // ChainNotify returns channel with chain head updates. // First message is guaranteed to be of len == 1, and type == 'current'. - ChainNotify(context.Context) (<-chan []*store.HeadChange, error) //perm:read + ChainNotify(context.Context) (<-chan []*types.HeadChange, error) //perm:read // ChainHead returns the current head of the chain. ChainHead(context.Context) (*types.TipSet, error) //perm:read @@ -161,7 +159,7 @@ type FullNode interface { // tRR // ``` // Would return `[revert(tBA), apply(tAB), apply(tAA)]` - ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*store.HeadChange, error) //perm:read + ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*types.HeadChange, error) //perm:read // ChainExport returns a stream of bytes with CAR dump of chain data. // The exported chain data includes the header chain from the given tipset @@ -288,7 +286,7 @@ type FullNode interface { // MethodGroup: Miner MinerGetBaseInfo(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*types.MiningBaseInfo, error) //perm:read - MinerCreateBlock(context.Context, *BlockTemplate) (*types.BlockMsg, error) //perm:write + MinerCreateBlock(context.Context, *types.BlockTemplate) (*types.BlockMsg, error) //perm:write // // UX ? @@ -1071,7 +1069,7 @@ type ActiveSync struct { Base *types.TipSet Target *types.TipSet - Stage SyncStateStage + Stage types.SyncStateStage Height abi.ChainEpoch Start time.Time @@ -1085,39 +1083,6 @@ type SyncState struct { VMApplied uint64 } -type SyncStateStage int - -const ( - StageIdle = SyncStateStage(iota) - StageHeaders - StagePersistHeaders - StageMessages - StageSyncComplete - StageSyncErrored - StageFetchingMessages -) - -func (v SyncStateStage) String() string { - switch v { - case StageIdle: - return "idle" - case StageHeaders: - return "header sync" - case StagePersistHeaders: - return "persisting headers" - case StageMessages: - return "message sync" - case StageSyncComplete: - return "complete" - case StageSyncErrored: - return "error" - case StageFetchingMessages: - return "fetching messages" - default: - return fmt.Sprintf("", v) - } -} - type MpoolChange int const ( diff --git a/api/api_gateway.go b/api/api_gateway.go index 9d14e083ce2..ac816967508 100644 --- a/api/api_gateway.go +++ b/api/api_gateway.go @@ -12,7 +12,6 @@ import ( "github.com/filecoin-project/go-state-types/dline" apitypes "github.com/filecoin-project/lotus/api/types" - "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" ) @@ -38,11 +37,11 @@ type Gateway interface { ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error) ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) - ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*store.HeadChange, error) + ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*types.HeadChange, error) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetAfterHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) - ChainNotify(context.Context) (<-chan []*store.HeadChange, error) + ChainNotify(context.Context) (<-chan []*types.HeadChange, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error) ChainGetGenesis(context.Context) (*types.TipSet, error) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index 55d7774390b..23102d59dc9 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -42,6 +42,7 @@ import ( apitypes "github.com/filecoin-project/lotus/api/types" "github.com/filecoin-project/lotus/api/v0api" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/eth" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/repo/imports" @@ -124,7 +125,7 @@ func init() { addExample(api.MpoolChange(0)) addExample(network.Connected) addExample(dtypes.NetworkName("lotus")) - addExample(api.SyncStateStage(1)) + addExample(types.SyncStateStage(1)) addExample(api.FullAPIVersion1) addExample(api.PCHInbound) addExample(time.Minute) diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 809a891ed7f..fdf272b08a0 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -36,7 +36,6 @@ import ( api "github.com/filecoin-project/lotus/api" apitypes "github.com/filecoin-project/lotus/api/types" miner0 "github.com/filecoin-project/lotus/chain/actors/builtin/miner" - store "github.com/filecoin-project/lotus/chain/store" types "github.com/filecoin-project/lotus/chain/types" alerting "github.com/filecoin-project/lotus/journal/alerting" dtypes "github.com/filecoin-project/lotus/node/modules/dtypes" @@ -275,10 +274,10 @@ func (mr *MockFullNodeMockRecorder) ChainGetParentReceipts(arg0, arg1 interface{ } // ChainGetPath mocks base method. -func (m *MockFullNode) ChainGetPath(arg0 context.Context, arg1, arg2 types.TipSetKey) ([]*store.HeadChange, error) { +func (m *MockFullNode) ChainGetPath(arg0 context.Context, arg1, arg2 types.TipSetKey) ([]*types.HeadChange, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChainGetPath", arg0, arg1, arg2) - ret0, _ := ret[0].([]*store.HeadChange) + ret0, _ := ret[0].([]*types.HeadChange) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -365,10 +364,10 @@ func (mr *MockFullNodeMockRecorder) ChainHead(arg0 interface{}) *gomock.Call { } // ChainNotify mocks base method. -func (m *MockFullNode) ChainNotify(arg0 context.Context) (<-chan []*store.HeadChange, error) { +func (m *MockFullNode) ChainNotify(arg0 context.Context) (<-chan []*types.HeadChange, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChainNotify", arg0) - ret0, _ := ret[0].(<-chan []*store.HeadChange) + ret0, _ := ret[0].(<-chan []*types.HeadChange) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 0902073d315..9fb562ddd13 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -35,7 +35,6 @@ import ( apitypes "github.com/filecoin-project/lotus/api/types" "github.com/filecoin-project/lotus/chain/actors/builtin" lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" - "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/journal/alerting" _ "github.com/filecoin-project/lotus/lib/sigs/delegated" @@ -136,7 +135,7 @@ type FullNodeStruct struct { ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` - ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) `perm:"read"` + ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*types.HeadChange, error) `perm:"read"` ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `perm:"read"` @@ -148,7 +147,7 @@ type FullNodeStruct struct { ChainHead func(p0 context.Context) (*types.TipSet, error) `perm:"read"` - ChainNotify func(p0 context.Context) (<-chan []*store.HeadChange, error) `perm:"read"` + ChainNotify func(p0 context.Context) (<-chan []*types.HeadChange, error) `perm:"read"` ChainPrune func(p0 context.Context, p1 PruneOpts) error `perm:"admin"` @@ -580,7 +579,7 @@ type GatewayStruct struct { ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `` - ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) `` + ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*types.HeadChange, error) `` ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `` @@ -592,7 +591,7 @@ type GatewayStruct struct { ChainHead func(p0 context.Context) (*types.TipSet, error) `` - ChainNotify func(p0 context.Context) (<-chan []*store.HeadChange, error) `` + ChainNotify func(p0 context.Context) (<-chan []*types.HeadChange, error) `` ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` @@ -1383,15 +1382,15 @@ func (s *FullNodeStub) ChainGetParentReceipts(p0 context.Context, p1 cid.Cid) ([ return *new([]*types.MessageReceipt), ErrNotSupported } -func (s *FullNodeStruct) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) { +func (s *FullNodeStruct) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*types.HeadChange, error) { if s.Internal.ChainGetPath == nil { - return *new([]*store.HeadChange), ErrNotSupported + return *new([]*types.HeadChange), ErrNotSupported } return s.Internal.ChainGetPath(p0, p1, p2) } -func (s *FullNodeStub) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) { - return *new([]*store.HeadChange), ErrNotSupported +func (s *FullNodeStub) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*types.HeadChange, error) { + return *new([]*types.HeadChange), ErrNotSupported } func (s *FullNodeStruct) ChainGetTipSet(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) { @@ -1449,14 +1448,14 @@ func (s *FullNodeStub) ChainHead(p0 context.Context) (*types.TipSet, error) { return nil, ErrNotSupported } -func (s *FullNodeStruct) ChainNotify(p0 context.Context) (<-chan []*store.HeadChange, error) { +func (s *FullNodeStruct) ChainNotify(p0 context.Context) (<-chan []*types.HeadChange, error) { if s.Internal.ChainNotify == nil { return nil, ErrNotSupported } return s.Internal.ChainNotify(p0) } -func (s *FullNodeStub) ChainNotify(p0 context.Context) (<-chan []*store.HeadChange, error) { +func (s *FullNodeStub) ChainNotify(p0 context.Context) (<-chan []*types.HeadChange, error) { return nil, ErrNotSupported } @@ -3770,15 +3769,15 @@ func (s *GatewayStub) ChainGetParentReceipts(p0 context.Context, p1 cid.Cid) ([] return *new([]*types.MessageReceipt), ErrNotSupported } -func (s *GatewayStruct) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) { +func (s *GatewayStruct) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*types.HeadChange, error) { if s.Internal.ChainGetPath == nil { - return *new([]*store.HeadChange), ErrNotSupported + return *new([]*types.HeadChange), ErrNotSupported } return s.Internal.ChainGetPath(p0, p1, p2) } -func (s *GatewayStub) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) { - return *new([]*store.HeadChange), ErrNotSupported +func (s *GatewayStub) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*types.HeadChange, error) { + return *new([]*types.HeadChange), ErrNotSupported } func (s *GatewayStruct) ChainGetTipSet(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) { @@ -3836,14 +3835,14 @@ func (s *GatewayStub) ChainHead(p0 context.Context) (*types.TipSet, error) { return nil, ErrNotSupported } -func (s *GatewayStruct) ChainNotify(p0 context.Context) (<-chan []*store.HeadChange, error) { +func (s *GatewayStruct) ChainNotify(p0 context.Context) (<-chan []*types.HeadChange, error) { if s.Internal.ChainNotify == nil { return nil, ErrNotSupported } return s.Internal.ChainNotify(p0) } -func (s *GatewayStub) ChainNotify(p0 context.Context) (<-chan []*store.HeadChange, error) { +func (s *GatewayStub) ChainNotify(p0 context.Context) (<-chan []*types.HeadChange, error) { return nil, ErrNotSupported } diff --git a/api/v0api/full.go b/api/v0api/full.go index c1fb641427e..721d1f8fc3a 100644 --- a/api/v0api/full.go +++ b/api/v0api/full.go @@ -24,7 +24,6 @@ import ( "github.com/filecoin-project/lotus/api" apitypes "github.com/filecoin-project/lotus/api/types" lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" - "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" marketevents "github.com/filecoin-project/lotus/markets/loggers" "github.com/filecoin-project/lotus/node/modules/dtypes" @@ -61,7 +60,7 @@ type FullNode interface { // ChainNotify returns channel with chain head updates. // First message is guaranteed to be of len == 1, and type == 'current'. - ChainNotify(context.Context) (<-chan []*store.HeadChange, error) //perm:read + ChainNotify(context.Context) (<-chan []*types.HeadChange, error) //perm:read // ChainHead returns the current head of the chain. ChainHead(context.Context) (*types.TipSet, error) //perm:read @@ -153,7 +152,7 @@ type FullNode interface { // tRR // ``` // Would return `[revert(tBA), apply(tAB), apply(tAA)]` - ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*store.HeadChange, error) //perm:read + ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*types.HeadChange, error) //perm:read // ChainExport returns a stream of bytes with CAR dump of chain data. // The exported chain data includes the header chain from the given tipset diff --git a/api/v0api/gateway.go b/api/v0api/gateway.go index db38bdd97dd..3d02e3ea41e 100644 --- a/api/v0api/gateway.go +++ b/api/v0api/gateway.go @@ -13,7 +13,6 @@ import ( abinetwork "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" ) @@ -42,7 +41,7 @@ type Gateway interface { ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) - ChainNotify(context.Context) (<-chan []*store.HeadChange, error) + ChainNotify(context.Context) (<-chan []*types.HeadChange, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) diff --git a/api/v0api/proxy_gen.go b/api/v0api/proxy_gen.go index d2406898c14..36c08a6db8e 100644 --- a/api/v0api/proxy_gen.go +++ b/api/v0api/proxy_gen.go @@ -26,7 +26,6 @@ import ( "github.com/filecoin-project/lotus/api" apitypes "github.com/filecoin-project/lotus/api/types" lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" - "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" marketevents "github.com/filecoin-project/lotus/markets/loggers" "github.com/filecoin-project/lotus/node/modules/dtypes" @@ -63,7 +62,7 @@ type FullNodeStruct struct { ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` - ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) `perm:"read"` + ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*types.HeadChange, error) `perm:"read"` ChainGetRandomnessFromBeacon func(p0 context.Context, p1 types.TipSetKey, p2 crypto.DomainSeparationTag, p3 abi.ChainEpoch, p4 []byte) (abi.Randomness, error) `perm:"read"` @@ -77,7 +76,7 @@ type FullNodeStruct struct { ChainHead func(p0 context.Context) (*types.TipSet, error) `perm:"read"` - ChainNotify func(p0 context.Context) (<-chan []*store.HeadChange, error) `perm:"read"` + ChainNotify func(p0 context.Context) (<-chan []*types.HeadChange, error) `perm:"read"` ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` @@ -439,7 +438,7 @@ type GatewayStruct struct { ChainHead func(p0 context.Context) (*types.TipSet, error) `` - ChainNotify func(p0 context.Context) (<-chan []*store.HeadChange, error) `` + ChainNotify func(p0 context.Context) (<-chan []*types.HeadChange, error) `` ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` @@ -617,15 +616,15 @@ func (s *FullNodeStub) ChainGetParentReceipts(p0 context.Context, p1 cid.Cid) ([ return *new([]*types.MessageReceipt), ErrNotSupported } -func (s *FullNodeStruct) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) { +func (s *FullNodeStruct) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*types.HeadChange, error) { if s.Internal.ChainGetPath == nil { - return *new([]*store.HeadChange), ErrNotSupported + return *new([]*types.HeadChange), ErrNotSupported } return s.Internal.ChainGetPath(p0, p1, p2) } -func (s *FullNodeStub) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*store.HeadChange, error) { - return *new([]*store.HeadChange), ErrNotSupported +func (s *FullNodeStub) ChainGetPath(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*types.HeadChange, error) { + return *new([]*types.HeadChange), ErrNotSupported } func (s *FullNodeStruct) ChainGetRandomnessFromBeacon(p0 context.Context, p1 types.TipSetKey, p2 crypto.DomainSeparationTag, p3 abi.ChainEpoch, p4 []byte) (abi.Randomness, error) { @@ -694,14 +693,14 @@ func (s *FullNodeStub) ChainHead(p0 context.Context) (*types.TipSet, error) { return nil, ErrNotSupported } -func (s *FullNodeStruct) ChainNotify(p0 context.Context) (<-chan []*store.HeadChange, error) { +func (s *FullNodeStruct) ChainNotify(p0 context.Context) (<-chan []*types.HeadChange, error) { if s.Internal.ChainNotify == nil { return nil, ErrNotSupported } return s.Internal.ChainNotify(p0) } -func (s *FullNodeStub) ChainNotify(p0 context.Context) (<-chan []*store.HeadChange, error) { +func (s *FullNodeStub) ChainNotify(p0 context.Context) (<-chan []*types.HeadChange, error) { return nil, ErrNotSupported } @@ -2630,14 +2629,14 @@ func (s *GatewayStub) ChainHead(p0 context.Context) (*types.TipSet, error) { return nil, ErrNotSupported } -func (s *GatewayStruct) ChainNotify(p0 context.Context) (<-chan []*store.HeadChange, error) { +func (s *GatewayStruct) ChainNotify(p0 context.Context) (<-chan []*types.HeadChange, error) { if s.Internal.ChainNotify == nil { return nil, ErrNotSupported } return s.Internal.ChainNotify(p0) } -func (s *GatewayStub) ChainNotify(p0 context.Context) (<-chan []*store.HeadChange, error) { +func (s *GatewayStub) ChainNotify(p0 context.Context) (<-chan []*types.HeadChange, error) { return nil, ErrNotSupported } diff --git a/api/v0api/v0mocks/mock_full.go b/api/v0api/v0mocks/mock_full.go index 4e79a5dbaec..896d2edde56 100644 --- a/api/v0api/v0mocks/mock_full.go +++ b/api/v0api/v0mocks/mock_full.go @@ -37,7 +37,6 @@ import ( apitypes "github.com/filecoin-project/lotus/api/types" v0api "github.com/filecoin-project/lotus/api/v0api" miner0 "github.com/filecoin-project/lotus/chain/actors/builtin/miner" - store "github.com/filecoin-project/lotus/chain/store" types "github.com/filecoin-project/lotus/chain/types" alerting "github.com/filecoin-project/lotus/journal/alerting" marketevents "github.com/filecoin-project/lotus/markets/loggers" @@ -263,10 +262,10 @@ func (mr *MockFullNodeMockRecorder) ChainGetParentReceipts(arg0, arg1 interface{ } // ChainGetPath mocks base method. -func (m *MockFullNode) ChainGetPath(arg0 context.Context, arg1, arg2 types.TipSetKey) ([]*store.HeadChange, error) { +func (m *MockFullNode) ChainGetPath(arg0 context.Context, arg1, arg2 types.TipSetKey) ([]*types.HeadChange, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChainGetPath", arg0, arg1, arg2) - ret0, _ := ret[0].([]*store.HeadChange) + ret0, _ := ret[0].([]*types.HeadChange) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -368,10 +367,10 @@ func (mr *MockFullNodeMockRecorder) ChainHead(arg0 interface{}) *gomock.Call { } // ChainNotify mocks base method. -func (m *MockFullNode) ChainNotify(arg0 context.Context) (<-chan []*store.HeadChange, error) { +func (m *MockFullNode) ChainNotify(arg0 context.Context) (<-chan []*types.HeadChange, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChainNotify", arg0) - ret0, _ := ret[0].(<-chan []*store.HeadChange) + ret0, _ := ret[0].(<-chan []*types.HeadChange) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 573dce338ac57a1925a1076dfafd451b11b8920a..6a008bae5e1701499a711c43b95068517ad1decc 100644 GIT binary patch delta 28068 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 GVE+M}aDZ0; delta 28101 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 LB&{qZ6v+PpmB)3) diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index 164a55cd319dbb2d9e18fe56df9de54bce14dc9f..d506e228fce51d76a1d1099159e3da31512a07fa 100644 GIT binary patch delta 4772 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 delta 4784 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 Kv{-q~@c;nC^no=1 diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index f3c444e98373cdf597846d89239a38a2309ae385..ca337d81054497d80afab9a569404583684276e0 100644 GIT binary patch delta 14480 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 delta 14482 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 diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index a8fe5e17d747a37a8a055a0ec09c8719ab9908ba..809be5a10872b339a410ebaebc6dfd675cbe2fb6 100644 GIT binary patch delta 4078 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 XWhQ=K@5w-*`}^DGR{S{u9MJy&np*XY diff --git a/chain/events/cache.go b/chain/events/cache.go index c7b1ec3120c..0861c1776cc 100644 --- a/chain/events/cache.go +++ b/chain/events/cache.go @@ -8,13 +8,12 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" ) type uncachedAPI interface { - ChainNotify(context.Context) (<-chan []*store.HeadChange, error) - ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*store.HeadChange, error) + ChainNotify(context.Context) (<-chan []*types.HeadChange, error) + ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*types.HeadChange, error) StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*types.MsgLookup, error) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) // optional / for CalledMsg diff --git a/chain/events/events.go b/chain/events/events.go index 18faa3005ca..d73972b51e7 100644 --- a/chain/events/events.go +++ b/chain/events/events.go @@ -11,7 +11,6 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" - "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" ) @@ -30,14 +29,14 @@ type TipSetObserver interface { } type EventAPI interface { - ChainNotify(context.Context) (<-chan []*store.HeadChange, error) + ChainNotify(context.Context) (<-chan []*types.HeadChange, error) ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) ChainGetTipSetAfterHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) ChainHead(context.Context) (*types.TipSet, error) StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*types.MsgLookup, error) ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error) - ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*store.HeadChange, error) + ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*types.HeadChange, error) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) // optional / for CalledMsg } diff --git a/chain/events/events_test.go b/chain/events/events_test.go index f944597e55b..3f481c789b2 100644 --- a/chain/events/events_test.go +++ b/chain/events/events_test.go @@ -45,7 +45,7 @@ type fakeCS struct { mu sync.Mutex waitSub chan struct{} - subCh chan<- []*store.HeadChange + subCh chan<- []*types.HeadChange callNumber map[string]int } @@ -71,7 +71,7 @@ func (fcs *fakeCS) ChainHead(ctx context.Context) (*types.TipSet, error) { panic("implement me") } -func (fcs *fakeCS) ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*store.HeadChange, error) { +func (fcs *fakeCS) ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*types.HeadChange, error) { fcs.mu.Lock() fcs.callNumber["ChainGetPath"] = fcs.callNumber["ChainGetPath"] + 1 fcs.mu.Unlock() @@ -94,12 +94,12 @@ func (fcs *fakeCS) ChainGetPath(ctx context.Context, from, to types.TipSetKey) ( return nil, err } - path := make([]*store.HeadChange, len(revert)+len(apply)) + path := make([]*types.HeadChange, len(revert)+len(apply)) for i, r := range revert { - path[i] = &store.HeadChange{Type: store.HCRevert, Val: r} + path[i] = &types.HeadChange{Type: store.HCRevert, Val: r} } for j, i := 0, len(apply)-1; i >= 0; j, i = j+1, i-1 { - path[j+len(revert)] = &store.HeadChange{Type: store.HCApply, Val: apply[i]} + path[j+len(revert)] = &types.HeadChange{Type: store.HCApply, Val: apply[i]} } return path, nil } @@ -184,12 +184,12 @@ func (fcs *fakeCS) makeTs(t *testing.T, parents []cid.Cid, h abi.ChainEpoch, msg return ts } -func (fcs *fakeCS) ChainNotify(ctx context.Context) (<-chan []*store.HeadChange, error) { +func (fcs *fakeCS) ChainNotify(ctx context.Context) (<-chan []*types.HeadChange, error) { fcs.mu.Lock() defer fcs.mu.Unlock() fcs.callNumber["ChainNotify"] = fcs.callNumber["ChainNotify"] + 1 - out := make(chan []*store.HeadChange, 1) + out := make(chan []*types.HeadChange, 1) if fcs.subCh != nil { close(out) fcs.t.Error("already subscribed to notifications") @@ -201,7 +201,7 @@ func (fcs *fakeCS) ChainNotify(ctx context.Context) (<-chan []*store.HeadChange, return nil, err } - out <- []*store.HeadChange{{Type: store.HCCurrent, Val: best}} + out <- []*types.HeadChange{{Type: store.HCCurrent, Val: best}} fcs.subCh = out close(fcs.waitSub) @@ -266,16 +266,16 @@ func (fcs *fakeCS) dropSub() { func (fcs *fakeCS) sub(rev, app []*types.TipSet) { <-fcs.waitSub - notif := make([]*store.HeadChange, len(rev)+len(app)) + notif := make([]*types.HeadChange, len(rev)+len(app)) for i, r := range rev { - notif[i] = &store.HeadChange{ + notif[i] = &types.HeadChange{ Type: store.HCRevert, Val: r, } } for i, r := range app { - notif[i+len(rev)] = &store.HeadChange{ + notif[i+len(rev)] = &types.HeadChange{ Type: store.HCApply, Val: r, } diff --git a/chain/events/observer.go b/chain/events/observer.go index 820b2fe9d4d..e24d77827f4 100644 --- a/chain/events/observer.go +++ b/chain/events/observer.go @@ -80,7 +80,7 @@ func (o *observer) listenHeadChangesOnce(ctx context.Context) error { return xerrors.Errorf("listenHeadChanges ChainNotify call failed: %w", err) } - var cur []*store.HeadChange + var cur []*types.HeadChange var ok bool // Wait for first tipset or bail @@ -131,7 +131,7 @@ func (o *observer) listenHeadChangesOnce(ctx context.Context) error { return nil } -func (o *observer) applyChanges(ctx context.Context, changes []*store.HeadChange) error { +func (o *observer) applyChanges(ctx context.Context, changes []*types.HeadChange) error { // Used to wait for a prior notification round to finish (by tests) if len(changes) == 0 { return nil diff --git a/chain/store/store.go b/chain/store/store.go index 400e416a738..2fef4dff997 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -166,16 +166,16 @@ func NewChainStore(chainBs bstore.Blockstore, stateBs bstore.Blockstore, ds dsto cs.pubLk.Lock() defer cs.pubLk.Unlock() - notif := make([]*HeadChange, len(rev)+len(app)) + notif := make([]*types.HeadChange, len(rev)+len(app)) for i, r := range rev { - notif[i] = &HeadChange{ + notif[i] = &types.HeadChange{ Type: HCRevert, Val: r, } } for i, r := range app { - notif[i+len(rev)] = &HeadChange{ + notif[i+len(rev)] = &types.HeadChange{ Type: HCApply, Val: r, } @@ -282,14 +282,14 @@ const ( HCCurrent = "current" ) -func (cs *ChainStore) SubHeadChanges(ctx context.Context) chan []*HeadChange { +func (cs *ChainStore) SubHeadChanges(ctx context.Context) chan []*types.HeadChange { cs.pubLk.Lock() subch := cs.bestTips.Sub("headchange") head := cs.GetHeaviestTipSet() cs.pubLk.Unlock() - out := make(chan []*HeadChange, 16) - out <- []*HeadChange{{ + out := make(chan []*types.HeadChange, 16) + out <- []*types.HeadChange{{ Type: HCCurrent, Val: head, }} @@ -315,7 +315,7 @@ func (cs *ChainStore) SubHeadChanges(ctx context.Context) chan []*HeadChange { return } select { - case out <- val.([]*HeadChange): + case out <- val.([]*types.HeadChange): default: log.Errorf("closing head change subscription due to slow reader") return @@ -1072,7 +1072,7 @@ func (cs *ChainStore) GetGenesis(ctx context.Context) (*types.BlockHeader, error // GetPath returns the sequence of atomic head change operations that // need to be applied in order to switch the head of the chain from the `from` // tipset to the `to` tipset. -func (cs *ChainStore) GetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*HeadChange, error) { +func (cs *ChainStore) GetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*types.HeadChange, error) { fts, err := cs.LoadTipSet(ctx, from) if err != nil { return nil, xerrors.Errorf("loading from tipset %s: %w", from, err) @@ -1086,12 +1086,12 @@ func (cs *ChainStore) GetPath(ctx context.Context, from types.TipSetKey, to type return nil, xerrors.Errorf("error getting tipset branches: %w", err) } - path := make([]*HeadChange, len(revert)+len(apply)) + path := make([]*types.HeadChange, len(revert)+len(apply)) for i, r := range revert { - path[i] = &HeadChange{Type: HCRevert, Val: r} + path[i] = &types.HeadChange{Type: HCRevert, Val: r} } for j, i := 0, len(apply)-1; i >= 0; j, i = j+1, i-1 { - path[j+len(revert)] = &HeadChange{Type: HCApply, Val: apply[i]} + path[j+len(revert)] = &types.HeadChange{Type: HCApply, Val: apply[i]} } return path, nil } @@ -1252,8 +1252,3 @@ func (cs *ChainStore) GetLatestBeaconEntry(ctx context.Context, ts *types.TipSet return nil, xerrors.Errorf("found NO beacon entries in the 20 latest tipsets") } - -type HeadChange struct { - Type string - Val *types.TipSet -} diff --git a/chain/sync.go b/chain/sync.go index ba28d3e79a9..18596cfc9ac 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -33,7 +33,6 @@ import ( // messages, regardless of specs-actors version. blockadt "github.com/filecoin-project/specs-actors/actors/util/adt" - "github.com/filecoin-project/lotus/api" bstore "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/beacon" @@ -983,10 +982,10 @@ func (syncer *Syncer) iterFullTipsets(ctx context.Context, headers []*types.TipS batchSize = i + 1 } - ss.SetStage(api.StageFetchingMessages) + ss.SetStage(types.StageFetchingMessages) startOffset := i + 1 - batchSize bstout, batchErr := syncer.fetchMessages(ctx, headers[startOffset:startOffset+batchSize], startOffset) - ss.SetStage(api.StageMessages) + ss.SetStage(types.StageMessages) if batchErr != nil { return xerrors.Errorf("failed to fetch messages: %w", batchErr) @@ -1196,7 +1195,7 @@ func (syncer *Syncer) collectChain(ctx context.Context, ts *types.TipSet, hts *t log.Errorf("collectChain headers[0] should be equal to sync target. Its not: %s != %s", headers[0].Cids(), ts.Cids()) } - ss.SetStage(api.StagePersistHeaders) + ss.SetStage(types.StagePersistHeaders) toPersist := make([]*types.BlockHeader, 0, len(headers)*int(build.BlocksPerEpoch)) for _, ts := range headers { @@ -1209,7 +1208,7 @@ func (syncer *Syncer) collectChain(ctx context.Context, ts *types.TipSet, hts *t } toPersist = nil - ss.SetStage(api.StageMessages) + ss.SetStage(types.StageMessages) if err := syncer.syncMessagesAndCheckState(ctx, headers); err != nil { err = xerrors.Errorf("collectChain syncMessages: %w", err) @@ -1217,7 +1216,7 @@ func (syncer *Syncer) collectChain(ctx context.Context, ts *types.TipSet, hts *t return err } - ss.SetStage(api.StageSyncComplete) + ss.SetStage(types.StageSyncComplete) log.Debugw("new tipset", "height", ts.Height(), "tipset", types.LogCids(ts.Cids())) return nil diff --git a/chain/sync_test.go b/chain/sync_test.go index 0faf86588a2..4f0905aeee9 100644 --- a/chain/sync_test.go +++ b/chain/sync_test.go @@ -1259,5 +1259,5 @@ func TestSyncState(t *testing.T) { state, err = clientNode.SyncState(tu.ctx) require.NoError(tu.t, err) require.Equal(tu.t, len(state.ActiveSyncs), 1) - require.Equal(tu.t, state.ActiveSyncs[0].Stage, api.StageSyncComplete) + require.Equal(tu.t, state.ActiveSyncs[0].Stage, types.StageSyncComplete) } diff --git a/chain/syncstate.go b/chain/syncstate.go index 527d6be4832..9d202204ca1 100644 --- a/chain/syncstate.go +++ b/chain/syncstate.go @@ -6,7 +6,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/types" ) @@ -15,7 +14,7 @@ type SyncerStateSnapshot struct { WorkerID uint64 Target *types.TipSet Base *types.TipSet - Stage api.SyncStateStage + Stage types.SyncStateStage Height abi.ChainEpoch Message string Start time.Time @@ -27,7 +26,7 @@ type SyncerState struct { data SyncerStateSnapshot } -func (ss *SyncerState) SetStage(v api.SyncStateStage) { +func (ss *SyncerState) SetStage(v types.SyncStateStage) { if ss == nil { return } @@ -35,7 +34,7 @@ func (ss *SyncerState) SetStage(v api.SyncStateStage) { ss.lk.Lock() defer ss.lk.Unlock() ss.data.Stage = v - if v == api.StageSyncComplete { + if v == types.StageSyncComplete { ss.data.End = build.Clock.Now() } } @@ -49,7 +48,7 @@ func (ss *SyncerState) Init(base, target *types.TipSet) { defer ss.lk.Unlock() ss.data.Target = target ss.data.Base = base - ss.data.Stage = api.StageHeaders + ss.data.Stage = types.StageHeaders ss.data.Height = 0 ss.data.Message = "" ss.data.Start = build.Clock.Now() @@ -74,7 +73,7 @@ func (ss *SyncerState) Error(err error) { ss.lk.Lock() defer ss.lk.Unlock() ss.data.Message = err.Error() - ss.data.Stage = api.StageSyncErrored + ss.data.Stage = types.StageSyncErrored ss.data.End = build.Clock.Now() } diff --git a/chain/types/head_change.go b/chain/types/head_change.go new file mode 100644 index 00000000000..12d3d894876 --- /dev/null +++ b/chain/types/head_change.go @@ -0,0 +1,6 @@ +package types + +type HeadChange struct { + Type string + Val *TipSet +} diff --git a/chain/types/mining_base_info.go b/chain/types/mining_base_info.go index d516cf88fa2..b46d368f806 100644 --- a/chain/types/mining_base_info.go +++ b/chain/types/mining_base_info.go @@ -3,6 +3,7 @@ package types import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/builtin" ) diff --git a/chain/types/sync_state_stage.go b/chain/types/sync_state_stage.go new file mode 100644 index 00000000000..42e9547e7bb --- /dev/null +++ b/chain/types/sync_state_stage.go @@ -0,0 +1,36 @@ +package types + +import "fmt" + +type SyncStateStage int + +const ( + StageIdle = SyncStateStage(iota) + StageHeaders + StagePersistHeaders + StageMessages + StageSyncComplete + StageSyncErrored + StageFetchingMessages +) + +func (v SyncStateStage) String() string { + switch v { + case StageIdle: + return "idle" + case StageHeaders: + return "header sync" + case StagePersistHeaders: + return "persisting headers" + case StageMessages: + return "message sync" + case StageSyncComplete: + return "complete" + case StageSyncErrored: + return "error" + case StageFetchingMessages: + return "fetching messages" + default: + return fmt.Sprintf("", v) + } +} diff --git a/cli/sync.go b/cli/sync.go index 02e4e381ff7..944f67bd143 100644 --- a/cli/sync.go +++ b/cli/sync.go @@ -10,7 +10,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api/v0api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/types" @@ -76,7 +75,7 @@ var SyncStatusCmd = &cli.Command{ } else { afmt.Printf("\tElapsed: %s\n", ss.End.Sub(ss.Start)) } - if ss.Stage == api.StageSyncErrored { + if ss.Stage == types.StageSyncErrored { afmt.Printf("\tError: %s\n", ss.Message) } } @@ -281,10 +280,10 @@ func SyncWait(ctx context.Context, napi v0api.FullNode, watch bool) error { working := -1 for i, ss := range state.ActiveSyncs { switch ss.Stage { - case api.StageSyncComplete: + case types.StageSyncComplete: default: working = i - case api.StageIdle: + case types.StageIdle: // not complete, not actively working } } diff --git a/cli/sync_test.go b/cli/sync_test.go index 456d165f293..a108d0a8892 100644 --- a/cli/sync_test.go +++ b/cli/sync_test.go @@ -35,7 +35,7 @@ func TestSyncStatus(t *testing.T) { WorkerID: 1, Base: ts1, Target: ts2, - Stage: api.StageMessages, + Stage: types.StageMessages, Height: abi.ChainEpoch(0), Start: start, End: end, diff --git a/cmd/lotus-shed/balancer.go b/cmd/lotus-shed/balancer.go index 34d53896b6b..7a50091c462 100644 --- a/cmd/lotus-shed/balancer.go +++ b/cmd/lotus-shed/balancer.go @@ -117,7 +117,7 @@ Supported roles: const confidence = 16 - var notifs <-chan []*store.HeadChange + var notifs <-chan []*types.HeadChange for { if notifs == nil { notifs, err = api.ChainNotify(ctx) diff --git a/gateway/node.go b/gateway/node.go index c95f7a3cc79..5a21094059d 100644 --- a/gateway/node.go +++ b/gateway/node.go @@ -22,7 +22,6 @@ import ( apitypes "github.com/filecoin-project/lotus/api/types" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" - "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/lib/sigs" _ "github.com/filecoin-project/lotus/lib/sigs/bls" @@ -56,8 +55,8 @@ type TargetAPI interface { ChainGetTipSetAfterHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) ChainHasObj(context.Context, cid.Cid) (bool, error) ChainHead(ctx context.Context) (*types.TipSet, error) - ChainNotify(context.Context) (<-chan []*store.HeadChange, error) - ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*store.HeadChange, error) + ChainNotify(context.Context) (<-chan []*types.HeadChange, error) + ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*types.HeadChange, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error) ChainPutObj(context.Context, blocks.Block) error ChainGetGenesis(context.Context) (*types.TipSet, error) @@ -303,14 +302,14 @@ func (gw *Node) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, er return gw.target.ChainGetNode(ctx, p) } -func (gw *Node) ChainNotify(ctx context.Context) (<-chan []*store.HeadChange, error) { +func (gw *Node) ChainNotify(ctx context.Context) (<-chan []*types.HeadChange, error) { if err := gw.limit(ctx, chainRateLimitTokens); err != nil { return nil, err } return gw.target.ChainNotify(ctx) } -func (gw *Node) ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*store.HeadChange, error) { +func (gw *Node) ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*types.HeadChange, error) { if err := gw.limit(ctx, chainRateLimitTokens); err != nil { return nil, err } diff --git a/itests/api_test.go b/itests/api_test.go index d9fe497aa76..e34409b2620 100644 --- a/itests/api_test.go +++ b/itests/api_test.go @@ -18,7 +18,6 @@ import ( lapi "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" - "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/itests/kit" ) @@ -245,7 +244,7 @@ func (ts *apiSuite) testSlowNotify(t *testing.T) { full, miner, _ := kit.EnsembleMinimal(t, ts.opts...) // Subscribe a bunch of times to make sure we fill up any RPC buffers. - var newHeadsChans []<-chan []*store.HeadChange + var newHeadsChans []<-chan []*types.HeadChange for i := 0; i < 100; i++ { newHeads, err := full.ChainNotify(ctx) require.NoError(t, err) diff --git a/markets/utils/converters.go b/markets/utils/converters.go index 3c4f6edde29..e3b860d626a 100644 --- a/markets/utils/converters.go +++ b/markets/utils/converters.go @@ -1,7 +1,6 @@ package utils import ( - "github.com/filecoin-project/lotus/chain/types" "github.com/libp2p/go-libp2p/core/peer" "github.com/multiformats/go-multiaddr" @@ -9,6 +8,8 @@ import ( "github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" + + "github.com/filecoin-project/lotus/chain/types" ) func NewStorageProviderInfo(address address.Address, miner address.Address, sectorSize abi.SectorSize, peer peer.ID, addrs []abi.Multiaddrs) storagemarket.StorageProviderInfo { diff --git a/node/health.go b/node/health.go index 05b53d02bbd..5af10f05825 100644 --- a/node/health.go +++ b/node/health.go @@ -10,7 +10,7 @@ import ( "github.com/libp2p/go-libp2p/core/network" lapi "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/chain/store" + "github.com/filecoin-project/lotus/chain/types" ) var healthlog = logging.Logger("healthcheck") @@ -48,7 +48,7 @@ func NewLiveHandler(api lapi.FullNode) *HealthHandler { ) var ( countdown int32 - headCh <-chan []*store.HeadChange + headCh <-chan []*types.HeadChange backoff time.Duration = minbackoff err error ) diff --git a/node/impl/full/chain.go b/node/impl/full/chain.go index f7c8ba00af1..e84ef616782 100644 --- a/node/impl/full/chain.go +++ b/node/impl/full/chain.go @@ -41,7 +41,7 @@ import ( var log = logging.Logger("fullnode") type ChainModuleAPI interface { - ChainNotify(context.Context) (<-chan []*store.HeadChange, error) + ChainNotify(context.Context) (<-chan []*types.HeadChange, error) ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) ChainHasObj(context.Context, cid.Cid) (bool, error) ChainHead(context.Context) (*types.TipSet, error) @@ -50,7 +50,7 @@ type ChainModuleAPI interface { ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) ChainGetTipSetAfterHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error) - ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*store.HeadChange, error) + ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*types.HeadChange, error) } var _ ChainModuleAPI = *new(api.FullNode) @@ -89,7 +89,7 @@ type ChainAPI struct { BaseBlockstore dtypes.BaseBlockstore } -func (m *ChainModule) ChainNotify(ctx context.Context) (<-chan []*store.HeadChange, error) { +func (m *ChainModule) ChainNotify(ctx context.Context) (<-chan []*types.HeadChange, error) { return m.Chain.SubHeadChanges(ctx), nil } @@ -105,7 +105,7 @@ func (m *ChainModule) ChainGetTipSet(ctx context.Context, key types.TipSetKey) ( return m.Chain.LoadTipSet(ctx, key) } -func (m *ChainModule) ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*store.HeadChange, error) { +func (m *ChainModule) ChainGetPath(ctx context.Context, from, to types.TipSetKey) ([]*types.HeadChange, error) { return m.Chain.GetPath(ctx, from, to) } @@ -137,7 +137,7 @@ func (m *ChainModule) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) (* }, nil } -func (a *ChainAPI) ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*store.HeadChange, error) { +func (a *ChainAPI) ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*types.HeadChange, error) { return a.Chain.GetPath(ctx, from, to) } diff --git a/storage/wdpost/wdpost_sched.go b/storage/wdpost/wdpost_sched.go index 083dc39d8b3..fc5f59537de 100644 --- a/storage/wdpost/wdpost_sched.go +++ b/storage/wdpost/wdpost_sched.go @@ -33,7 +33,7 @@ var log = logging.Logger("wdpost") type NodeAPI interface { ChainHead(context.Context) (*types.TipSet, error) - ChainNotify(context.Context) (<-chan []*store.HeadChange, error) + ChainNotify(context.Context) (<-chan []*types.HeadChange, error) StateMinerInfo(context.Context, address.Address, types.TipSetKey) (api.MinerInfo, error) StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) @@ -140,7 +140,7 @@ func (s *WindowPoStScheduler) Run(ctx context.Context) { s.ch.start() var ( - notifs <-chan []*store.HeadChange + notifs <-chan []*types.HeadChange err error gotCur bool ) diff --git a/tools/stats/headbuffer/head_buffer.go b/tools/stats/headbuffer/head_buffer.go index 5857c6017b0..656823e164f 100644 --- a/tools/stats/headbuffer/head_buffer.go +++ b/tools/stats/headbuffer/head_buffer.go @@ -3,7 +3,7 @@ package headbuffer import ( "container/list" - "github.com/filecoin-project/lotus/chain/store" + "github.com/filecoin-project/lotus/chain/types" ) type HeadChangeStackBuffer struct { @@ -27,12 +27,12 @@ func NewHeadChangeStackBuffer(size int) *HeadChangeStackBuffer { // Push adds a HeadChange to stack buffer. If the length of // the stack buffer grows larger than the initizlized size, the // oldest HeadChange is returned. -func (h *HeadChangeStackBuffer) Push(hc *store.HeadChange) (rethc *store.HeadChange) { +func (h *HeadChangeStackBuffer) Push(hc *types.HeadChange) (rethc *types.HeadChange) { if h.buffer.Len() >= h.size { var ok bool el := h.buffer.Front() - rethc, ok = el.Value.(*store.HeadChange) + rethc, ok = el.Value.(*types.HeadChange) if !ok { // This shouldn't be possible, this method is typed and is the only place data // pushed to the buffer. diff --git a/tools/stats/headbuffer/head_buffer_test.go b/tools/stats/headbuffer/head_buffer_test.go index 3b1d248cb1d..7a2ca87277b 100644 --- a/tools/stats/headbuffer/head_buffer_test.go +++ b/tools/stats/headbuffer/head_buffer_test.go @@ -6,40 +6,40 @@ import ( "github.com/stretchr/testify/require" - "github.com/filecoin-project/lotus/chain/store" + "github.com/filecoin-project/lotus/chain/types" ) func TestHeadBuffer(t *testing.T) { //stm: @TOOLS_HEAD_BUFFER_PUSH_001, @TOOLS_HEAD_BUFFER_POP_001 t.Run("Straight Push through", func(t *testing.T) { hb := NewHeadChangeStackBuffer(5) - require.Nil(t, hb.Push(&store.HeadChange{Type: "1"})) - require.Nil(t, hb.Push(&store.HeadChange{Type: "2"})) - require.Nil(t, hb.Push(&store.HeadChange{Type: "3"})) - require.Nil(t, hb.Push(&store.HeadChange{Type: "4"})) - require.Nil(t, hb.Push(&store.HeadChange{Type: "5"})) + require.Nil(t, hb.Push(&types.HeadChange{Type: "1"})) + require.Nil(t, hb.Push(&types.HeadChange{Type: "2"})) + require.Nil(t, hb.Push(&types.HeadChange{Type: "3"})) + require.Nil(t, hb.Push(&types.HeadChange{Type: "4"})) + require.Nil(t, hb.Push(&types.HeadChange{Type: "5"})) - hc := hb.Push(&store.HeadChange{Type: "6"}) + hc := hb.Push(&types.HeadChange{Type: "6"}) require.Equal(t, hc.Type, "1") }) t.Run("Reverts", func(t *testing.T) { hb := NewHeadChangeStackBuffer(5) - require.Nil(t, hb.Push(&store.HeadChange{Type: "1"})) - require.Nil(t, hb.Push(&store.HeadChange{Type: "2"})) - require.Nil(t, hb.Push(&store.HeadChange{Type: "3"})) + require.Nil(t, hb.Push(&types.HeadChange{Type: "1"})) + require.Nil(t, hb.Push(&types.HeadChange{Type: "2"})) + require.Nil(t, hb.Push(&types.HeadChange{Type: "3"})) hb.Pop() - require.Nil(t, hb.Push(&store.HeadChange{Type: "3a"})) + require.Nil(t, hb.Push(&types.HeadChange{Type: "3a"})) hb.Pop() - require.Nil(t, hb.Push(&store.HeadChange{Type: "3b"})) - require.Nil(t, hb.Push(&store.HeadChange{Type: "4"})) - require.Nil(t, hb.Push(&store.HeadChange{Type: "5"})) + require.Nil(t, hb.Push(&types.HeadChange{Type: "3b"})) + require.Nil(t, hb.Push(&types.HeadChange{Type: "4"})) + require.Nil(t, hb.Push(&types.HeadChange{Type: "5"})) - hc := hb.Push(&store.HeadChange{Type: "6"}) + hc := hb.Push(&types.HeadChange{Type: "6"}) require.Equal(t, hc.Type, "1") - hc = hb.Push(&store.HeadChange{Type: "7"}) + hc = hb.Push(&types.HeadChange{Type: "7"}) require.Equal(t, hc.Type, "2") - hc = hb.Push(&store.HeadChange{Type: "8"}) + hc = hb.Push(&types.HeadChange{Type: "8"}) require.Equal(t, hc.Type, "3b") }) } diff --git a/tools/stats/sync/sync.go b/tools/stats/sync/sync.go index 13b12432b26..0dd1111416a 100644 --- a/tools/stats/sync/sync.go +++ b/tools/stats/sync/sync.go @@ -39,10 +39,10 @@ func SyncWait(ctx context.Context, napi SyncWaitApi) error { working := -1 for i, ss := range state.ActiveSyncs { switch ss.Stage { - case api.StageSyncComplete: + case types.StageSyncComplete: default: working = i - case api.StageIdle: + case types.StageIdle: // not complete, not actively working } } @@ -85,7 +85,7 @@ func SyncWait(ctx context.Context, napi SyncWaitApi) error { } type BufferedTipsetChannelApi interface { - ChainNotify(context.Context) (<-chan []*store.HeadChange, error) + ChainNotify(context.Context) (<-chan []*types.HeadChange, error) Version(context.Context) (api.APIVersion, error) ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error) } From b5f126a0020a90c73531925b36249206e2da1657 Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Wed, 14 Dec 2022 01:12:52 -0500 Subject: [PATCH 8/8] Move Eth files to chain/eth --- api/api_full.go | 57 ++-- api/docgen/docgen.go | 8 +- api/mocks/mock_full.go | 89 +++--- api/proxy_gen.go | 214 +++++++------- chain/consensus/filcns/filecoin.go | 4 +- {api => chain/eth}/eth_transactions.go | 2 +- {api => chain/eth}/eth_transactions_test.go | 2 +- {api => chain/eth}/eth_types.go | 2 +- {api => chain/eth}/eth_types_test.go | 2 +- {api => chain/eth}/rlp.go | 2 +- {api => chain/eth}/rlp_test.go | 2 +- chain/messagepool/messagepool.go | 5 +- node/impl/full/dummy.go | 64 ++--- node/impl/full/eth.go | 297 ++++++++++---------- 14 files changed, 377 insertions(+), 373 deletions(-) rename {api => chain/eth}/eth_transactions.go (99%) rename {api => chain/eth}/eth_transactions_test.go (99%) rename {api => chain/eth}/eth_types.go (99%) rename {api => chain/eth}/eth_types_test.go (99%) rename {api => chain/eth}/rlp.go (99%) rename {api => chain/eth}/rlp_test.go (99%) diff --git a/api/api_full.go b/api/api_full.go index 7d88d64eb50..32ba9199d48 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -27,6 +27,7 @@ import ( apitypes "github.com/filecoin-project/lotus/api/types" lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/builtin/power" + "github.com/filecoin-project/lotus/chain/eth" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/repo/imports" @@ -760,37 +761,37 @@ type FullNode interface { // These methods are used for Ethereum-compatible JSON-RPC calls // // EthAccounts will always return [] since we don't expect Lotus to manage private keys - EthAccounts(ctx context.Context) ([]EthAddress, error) //perm:read + EthAccounts(ctx context.Context) ([]eth.EthAddress, error) //perm:read // EthBlockNumber returns the height of the latest (heaviest) TipSet - EthBlockNumber(ctx context.Context) (EthUint64, error) //perm:read + EthBlockNumber(ctx context.Context) (eth.EthUint64, error) //perm:read // EthGetBlockTransactionCountByNumber returns the number of messages in the TipSet - EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum EthUint64) (EthUint64, error) //perm:read + EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum eth.EthUint64) (eth.EthUint64, error) //perm:read // EthGetBlockTransactionCountByHash returns the number of messages in the TipSet - EthGetBlockTransactionCountByHash(ctx context.Context, blkHash EthHash) (EthUint64, error) //perm:read - - EthGetBlockByHash(ctx context.Context, blkHash EthHash, fullTxInfo bool) (EthBlock, error) //perm:read - EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (EthBlock, error) //perm:read - EthGetTransactionByHash(ctx context.Context, txHash *EthHash) (*EthTx, error) //perm:read - EthGetTransactionCount(ctx context.Context, sender EthAddress, blkOpt string) (EthUint64, error) //perm:read - EthGetTransactionReceipt(ctx context.Context, txHash EthHash) (*EthTxReceipt, error) //perm:read - EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash EthHash, txIndex EthUint64) (EthTx, error) //perm:read - EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum EthUint64, txIndex EthUint64) (EthTx, error) //perm:read - - EthGetCode(ctx context.Context, address EthAddress, blkOpt string) (EthBytes, error) //perm:read - EthGetStorageAt(ctx context.Context, address EthAddress, position EthBytes, blkParam string) (EthBytes, error) //perm:read - EthGetBalance(ctx context.Context, address EthAddress, blkParam string) (EthBigInt, error) //perm:read - EthChainId(ctx context.Context) (EthUint64, error) //perm:read - NetVersion(ctx context.Context) (string, error) //perm:read - NetListening(ctx context.Context) (bool, error) //perm:read - EthProtocolVersion(ctx context.Context) (EthUint64, error) //perm:read - EthGasPrice(ctx context.Context) (EthBigInt, error) //perm:read - EthFeeHistory(ctx context.Context, blkCount EthUint64, newestBlk string, rewardPercentiles []float64) (EthFeeHistory, error) //perm:read - - EthMaxPriorityFeePerGas(ctx context.Context) (EthBigInt, error) //perm:read - EthEstimateGas(ctx context.Context, tx EthCall) (EthUint64, error) //perm:read - EthCall(ctx context.Context, tx EthCall, blkParam string) (EthBytes, error) //perm:read - - EthSendRawTransaction(ctx context.Context, rawTx EthBytes) (EthHash, error) //perm:read + EthGetBlockTransactionCountByHash(ctx context.Context, blkHash eth.EthHash) (eth.EthUint64, error) //perm:read + + EthGetBlockByHash(ctx context.Context, blkHash eth.EthHash, fullTxInfo bool) (eth.EthBlock, error) //perm:read + EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (eth.EthBlock, error) //perm:read + EthGetTransactionByHash(ctx context.Context, txHash *eth.EthHash) (*eth.EthTx, error) //perm:read + EthGetTransactionCount(ctx context.Context, sender eth.EthAddress, blkOpt string) (eth.EthUint64, error) //perm:read + EthGetTransactionReceipt(ctx context.Context, txHash eth.EthHash) (*eth.EthTxReceipt, error) //perm:read + EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash eth.EthHash, txIndex eth.EthUint64) (eth.EthTx, error) //perm:read + EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum eth.EthUint64, txIndex eth.EthUint64) (eth.EthTx, error) //perm:read + + EthGetCode(ctx context.Context, address eth.EthAddress, blkOpt string) (eth.EthBytes, error) //perm:read + EthGetStorageAt(ctx context.Context, address eth.EthAddress, position eth.EthBytes, blkParam string) (eth.EthBytes, error) //perm:read + EthGetBalance(ctx context.Context, address eth.EthAddress, blkParam string) (eth.EthBigInt, error) //perm:read + EthChainId(ctx context.Context) (eth.EthUint64, error) //perm:read + NetVersion(ctx context.Context) (string, error) //perm:read + NetListening(ctx context.Context) (bool, error) //perm:read + EthProtocolVersion(ctx context.Context) (eth.EthUint64, error) //perm:read + EthGasPrice(ctx context.Context) (eth.EthBigInt, error) //perm:read + EthFeeHistory(ctx context.Context, blkCount eth.EthUint64, newestBlk string, rewardPercentiles []float64) (eth.EthFeeHistory, error) //perm:read + + EthMaxPriorityFeePerGas(ctx context.Context) (eth.EthBigInt, error) //perm:read + EthEstimateGas(ctx context.Context, tx eth.EthCall) (eth.EthUint64, error) //perm:read + EthCall(ctx context.Context, tx eth.EthCall, blkParam string) (eth.EthBytes, error) //perm:read + + EthSendRawTransaction(ctx context.Context, rawTx eth.EthBytes) (eth.EthHash, error) //perm:read // CreateBackup creates node backup onder the specified file name. The // method requires that the lotus daemon is running with the diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index 23102d59dc9..dee0e40b98c 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -370,16 +370,16 @@ func init() { }, }) - ethint := api.EthUint64(5) + ethint := eth.EthUint64(5) addExample(ethint) addExample(ðint) - ethaddr, _ := api.EthAddressFromHex("0x5CbEeCF99d3fDB3f25E309Cc264f240bb0664031") + ethaddr, _ := eth.EthAddressFromHex("0x5CbEeCF99d3fDB3f25E309Cc264f240bb0664031") addExample(ðaddr) - ethhash, _ := api.NewEthHashFromCid(c) + ethhash, _ := eth.NewEthHashFromCid(c) addExample(ðhash) - ethFeeHistoryReward := [][]api.EthBigInt{} + ethFeeHistoryReward := [][]eth.EthBigInt{} addExample(ðFeeHistoryReward) addExample(&uuid.UUID{}) } diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index fdf272b08a0..087d9882bc9 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -36,6 +36,7 @@ import ( api "github.com/filecoin-project/lotus/api" apitypes "github.com/filecoin-project/lotus/api/types" miner0 "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + eth "github.com/filecoin-project/lotus/chain/eth" types "github.com/filecoin-project/lotus/chain/types" alerting "github.com/filecoin-project/lotus/journal/alerting" dtypes "github.com/filecoin-project/lotus/node/modules/dtypes" @@ -922,10 +923,10 @@ func (mr *MockFullNodeMockRecorder) Discover(arg0 interface{}) *gomock.Call { } // EthAccounts mocks base method. -func (m *MockFullNode) EthAccounts(arg0 context.Context) ([]api.EthAddress, error) { +func (m *MockFullNode) EthAccounts(arg0 context.Context) ([]eth.EthAddress, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthAccounts", arg0) - ret0, _ := ret[0].([]api.EthAddress) + ret0, _ := ret[0].([]eth.EthAddress) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -937,10 +938,10 @@ func (mr *MockFullNodeMockRecorder) EthAccounts(arg0 interface{}) *gomock.Call { } // EthBlockNumber mocks base method. -func (m *MockFullNode) EthBlockNumber(arg0 context.Context) (api.EthUint64, error) { +func (m *MockFullNode) EthBlockNumber(arg0 context.Context) (eth.EthUint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthBlockNumber", arg0) - ret0, _ := ret[0].(api.EthUint64) + ret0, _ := ret[0].(eth.EthUint64) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -952,10 +953,10 @@ func (mr *MockFullNodeMockRecorder) EthBlockNumber(arg0 interface{}) *gomock.Cal } // EthCall mocks base method. -func (m *MockFullNode) EthCall(arg0 context.Context, arg1 api.EthCall, arg2 string) (api.EthBytes, error) { +func (m *MockFullNode) EthCall(arg0 context.Context, arg1 eth.EthCall, arg2 string) (eth.EthBytes, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthCall", arg0, arg1, arg2) - ret0, _ := ret[0].(api.EthBytes) + ret0, _ := ret[0].(eth.EthBytes) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -967,10 +968,10 @@ func (mr *MockFullNodeMockRecorder) EthCall(arg0, arg1, arg2 interface{}) *gomoc } // EthChainId mocks base method. -func (m *MockFullNode) EthChainId(arg0 context.Context) (api.EthUint64, error) { +func (m *MockFullNode) EthChainId(arg0 context.Context) (eth.EthUint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthChainId", arg0) - ret0, _ := ret[0].(api.EthUint64) + ret0, _ := ret[0].(eth.EthUint64) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -982,10 +983,10 @@ func (mr *MockFullNodeMockRecorder) EthChainId(arg0 interface{}) *gomock.Call { } // EthEstimateGas mocks base method. -func (m *MockFullNode) EthEstimateGas(arg0 context.Context, arg1 api.EthCall) (api.EthUint64, error) { +func (m *MockFullNode) EthEstimateGas(arg0 context.Context, arg1 eth.EthCall) (eth.EthUint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthEstimateGas", arg0, arg1) - ret0, _ := ret[0].(api.EthUint64) + ret0, _ := ret[0].(eth.EthUint64) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -997,10 +998,10 @@ func (mr *MockFullNodeMockRecorder) EthEstimateGas(arg0, arg1 interface{}) *gomo } // EthFeeHistory mocks base method. -func (m *MockFullNode) EthFeeHistory(arg0 context.Context, arg1 api.EthUint64, arg2 string, arg3 []float64) (api.EthFeeHistory, error) { +func (m *MockFullNode) EthFeeHistory(arg0 context.Context, arg1 eth.EthUint64, arg2 string, arg3 []float64) (eth.EthFeeHistory, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthFeeHistory", arg0, arg1, arg2, arg3) - ret0, _ := ret[0].(api.EthFeeHistory) + ret0, _ := ret[0].(eth.EthFeeHistory) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1012,10 +1013,10 @@ func (mr *MockFullNodeMockRecorder) EthFeeHistory(arg0, arg1, arg2, arg3 interfa } // EthGasPrice mocks base method. -func (m *MockFullNode) EthGasPrice(arg0 context.Context) (api.EthBigInt, error) { +func (m *MockFullNode) EthGasPrice(arg0 context.Context) (eth.EthBigInt, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGasPrice", arg0) - ret0, _ := ret[0].(api.EthBigInt) + ret0, _ := ret[0].(eth.EthBigInt) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1027,10 +1028,10 @@ func (mr *MockFullNodeMockRecorder) EthGasPrice(arg0 interface{}) *gomock.Call { } // EthGetBalance mocks base method. -func (m *MockFullNode) EthGetBalance(arg0 context.Context, arg1 api.EthAddress, arg2 string) (api.EthBigInt, error) { +func (m *MockFullNode) EthGetBalance(arg0 context.Context, arg1 eth.EthAddress, arg2 string) (eth.EthBigInt, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetBalance", arg0, arg1, arg2) - ret0, _ := ret[0].(api.EthBigInt) + ret0, _ := ret[0].(eth.EthBigInt) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1042,10 +1043,10 @@ func (mr *MockFullNodeMockRecorder) EthGetBalance(arg0, arg1, arg2 interface{}) } // EthGetBlockByHash mocks base method. -func (m *MockFullNode) EthGetBlockByHash(arg0 context.Context, arg1 api.EthHash, arg2 bool) (api.EthBlock, error) { +func (m *MockFullNode) EthGetBlockByHash(arg0 context.Context, arg1 eth.EthHash, arg2 bool) (eth.EthBlock, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetBlockByHash", arg0, arg1, arg2) - ret0, _ := ret[0].(api.EthBlock) + ret0, _ := ret[0].(eth.EthBlock) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1057,10 +1058,10 @@ func (mr *MockFullNodeMockRecorder) EthGetBlockByHash(arg0, arg1, arg2 interface } // EthGetBlockByNumber mocks base method. -func (m *MockFullNode) EthGetBlockByNumber(arg0 context.Context, arg1 string, arg2 bool) (api.EthBlock, error) { +func (m *MockFullNode) EthGetBlockByNumber(arg0 context.Context, arg1 string, arg2 bool) (eth.EthBlock, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetBlockByNumber", arg0, arg1, arg2) - ret0, _ := ret[0].(api.EthBlock) + ret0, _ := ret[0].(eth.EthBlock) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1072,10 +1073,10 @@ func (mr *MockFullNodeMockRecorder) EthGetBlockByNumber(arg0, arg1, arg2 interfa } // EthGetBlockTransactionCountByHash mocks base method. -func (m *MockFullNode) EthGetBlockTransactionCountByHash(arg0 context.Context, arg1 api.EthHash) (api.EthUint64, error) { +func (m *MockFullNode) EthGetBlockTransactionCountByHash(arg0 context.Context, arg1 eth.EthHash) (eth.EthUint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetBlockTransactionCountByHash", arg0, arg1) - ret0, _ := ret[0].(api.EthUint64) + ret0, _ := ret[0].(eth.EthUint64) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1087,10 +1088,10 @@ func (mr *MockFullNodeMockRecorder) EthGetBlockTransactionCountByHash(arg0, arg1 } // EthGetBlockTransactionCountByNumber mocks base method. -func (m *MockFullNode) EthGetBlockTransactionCountByNumber(arg0 context.Context, arg1 api.EthUint64) (api.EthUint64, error) { +func (m *MockFullNode) EthGetBlockTransactionCountByNumber(arg0 context.Context, arg1 eth.EthUint64) (eth.EthUint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetBlockTransactionCountByNumber", arg0, arg1) - ret0, _ := ret[0].(api.EthUint64) + ret0, _ := ret[0].(eth.EthUint64) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1102,10 +1103,10 @@ func (mr *MockFullNodeMockRecorder) EthGetBlockTransactionCountByNumber(arg0, ar } // EthGetCode mocks base method. -func (m *MockFullNode) EthGetCode(arg0 context.Context, arg1 api.EthAddress, arg2 string) (api.EthBytes, error) { +func (m *MockFullNode) EthGetCode(arg0 context.Context, arg1 eth.EthAddress, arg2 string) (eth.EthBytes, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetCode", arg0, arg1, arg2) - ret0, _ := ret[0].(api.EthBytes) + ret0, _ := ret[0].(eth.EthBytes) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1117,10 +1118,10 @@ func (mr *MockFullNodeMockRecorder) EthGetCode(arg0, arg1, arg2 interface{}) *go } // EthGetStorageAt mocks base method. -func (m *MockFullNode) EthGetStorageAt(arg0 context.Context, arg1 api.EthAddress, arg2 api.EthBytes, arg3 string) (api.EthBytes, error) { +func (m *MockFullNode) EthGetStorageAt(arg0 context.Context, arg1 eth.EthAddress, arg2 eth.EthBytes, arg3 string) (eth.EthBytes, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetStorageAt", arg0, arg1, arg2, arg3) - ret0, _ := ret[0].(api.EthBytes) + ret0, _ := ret[0].(eth.EthBytes) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1132,10 +1133,10 @@ func (mr *MockFullNodeMockRecorder) EthGetStorageAt(arg0, arg1, arg2, arg3 inter } // EthGetTransactionByBlockHashAndIndex mocks base method. -func (m *MockFullNode) EthGetTransactionByBlockHashAndIndex(arg0 context.Context, arg1 api.EthHash, arg2 api.EthUint64) (api.EthTx, error) { +func (m *MockFullNode) EthGetTransactionByBlockHashAndIndex(arg0 context.Context, arg1 eth.EthHash, arg2 eth.EthUint64) (eth.EthTx, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetTransactionByBlockHashAndIndex", arg0, arg1, arg2) - ret0, _ := ret[0].(api.EthTx) + ret0, _ := ret[0].(eth.EthTx) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1147,10 +1148,10 @@ func (mr *MockFullNodeMockRecorder) EthGetTransactionByBlockHashAndIndex(arg0, a } // EthGetTransactionByBlockNumberAndIndex mocks base method. -func (m *MockFullNode) EthGetTransactionByBlockNumberAndIndex(arg0 context.Context, arg1, arg2 api.EthUint64) (api.EthTx, error) { +func (m *MockFullNode) EthGetTransactionByBlockNumberAndIndex(arg0 context.Context, arg1, arg2 eth.EthUint64) (eth.EthTx, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetTransactionByBlockNumberAndIndex", arg0, arg1, arg2) - ret0, _ := ret[0].(api.EthTx) + ret0, _ := ret[0].(eth.EthTx) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1162,10 +1163,10 @@ func (mr *MockFullNodeMockRecorder) EthGetTransactionByBlockNumberAndIndex(arg0, } // EthGetTransactionByHash mocks base method. -func (m *MockFullNode) EthGetTransactionByHash(arg0 context.Context, arg1 *api.EthHash) (*api.EthTx, error) { +func (m *MockFullNode) EthGetTransactionByHash(arg0 context.Context, arg1 *eth.EthHash) (*eth.EthTx, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetTransactionByHash", arg0, arg1) - ret0, _ := ret[0].(*api.EthTx) + ret0, _ := ret[0].(*eth.EthTx) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1177,10 +1178,10 @@ func (mr *MockFullNodeMockRecorder) EthGetTransactionByHash(arg0, arg1 interface } // EthGetTransactionCount mocks base method. -func (m *MockFullNode) EthGetTransactionCount(arg0 context.Context, arg1 api.EthAddress, arg2 string) (api.EthUint64, error) { +func (m *MockFullNode) EthGetTransactionCount(arg0 context.Context, arg1 eth.EthAddress, arg2 string) (eth.EthUint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetTransactionCount", arg0, arg1, arg2) - ret0, _ := ret[0].(api.EthUint64) + ret0, _ := ret[0].(eth.EthUint64) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1192,10 +1193,10 @@ func (mr *MockFullNodeMockRecorder) EthGetTransactionCount(arg0, arg1, arg2 inte } // EthGetTransactionReceipt mocks base method. -func (m *MockFullNode) EthGetTransactionReceipt(arg0 context.Context, arg1 api.EthHash) (*api.EthTxReceipt, error) { +func (m *MockFullNode) EthGetTransactionReceipt(arg0 context.Context, arg1 eth.EthHash) (*eth.EthTxReceipt, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetTransactionReceipt", arg0, arg1) - ret0, _ := ret[0].(*api.EthTxReceipt) + ret0, _ := ret[0].(*eth.EthTxReceipt) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1207,10 +1208,10 @@ func (mr *MockFullNodeMockRecorder) EthGetTransactionReceipt(arg0, arg1 interfac } // EthMaxPriorityFeePerGas mocks base method. -func (m *MockFullNode) EthMaxPriorityFeePerGas(arg0 context.Context) (api.EthBigInt, error) { +func (m *MockFullNode) EthMaxPriorityFeePerGas(arg0 context.Context) (eth.EthBigInt, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthMaxPriorityFeePerGas", arg0) - ret0, _ := ret[0].(api.EthBigInt) + ret0, _ := ret[0].(eth.EthBigInt) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1222,10 +1223,10 @@ func (mr *MockFullNodeMockRecorder) EthMaxPriorityFeePerGas(arg0 interface{}) *g } // EthProtocolVersion mocks base method. -func (m *MockFullNode) EthProtocolVersion(arg0 context.Context) (api.EthUint64, error) { +func (m *MockFullNode) EthProtocolVersion(arg0 context.Context) (eth.EthUint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthProtocolVersion", arg0) - ret0, _ := ret[0].(api.EthUint64) + ret0, _ := ret[0].(eth.EthUint64) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1237,10 +1238,10 @@ func (mr *MockFullNodeMockRecorder) EthProtocolVersion(arg0 interface{}) *gomock } // EthSendRawTransaction mocks base method. -func (m *MockFullNode) EthSendRawTransaction(arg0 context.Context, arg1 api.EthBytes) (api.EthHash, error) { +func (m *MockFullNode) EthSendRawTransaction(arg0 context.Context, arg1 eth.EthBytes) (eth.EthHash, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthSendRawTransaction", arg0, arg1) - ret0, _ := ret[0].(api.EthHash) + ret0, _ := ret[0].(eth.EthHash) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 9fb562ddd13..cde69bae129 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -35,9 +35,9 @@ import ( apitypes "github.com/filecoin-project/lotus/api/types" "github.com/filecoin-project/lotus/chain/actors/builtin" lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "github.com/filecoin-project/lotus/chain/eth" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/journal/alerting" - _ "github.com/filecoin-project/lotus/lib/sigs/delegated" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/repo/imports" "github.com/filecoin-project/lotus/storage/pipeline/sealiface" @@ -219,49 +219,49 @@ type FullNodeStruct struct { CreateBackup func(p0 context.Context, p1 string) error `perm:"admin"` - EthAccounts func(p0 context.Context) ([]EthAddress, error) `perm:"read"` + EthAccounts func(p0 context.Context) ([]eth.EthAddress, error) `perm:"read"` - EthBlockNumber func(p0 context.Context) (EthUint64, error) `perm:"read"` + EthBlockNumber func(p0 context.Context) (eth.EthUint64, error) `perm:"read"` - EthCall func(p0 context.Context, p1 EthCall, p2 string) (EthBytes, error) `perm:"read"` + EthCall func(p0 context.Context, p1 eth.EthCall, p2 string) (eth.EthBytes, error) `perm:"read"` - EthChainId func(p0 context.Context) (EthUint64, error) `perm:"read"` + EthChainId func(p0 context.Context) (eth.EthUint64, error) `perm:"read"` - EthEstimateGas func(p0 context.Context, p1 EthCall) (EthUint64, error) `perm:"read"` + EthEstimateGas func(p0 context.Context, p1 eth.EthCall) (eth.EthUint64, error) `perm:"read"` - EthFeeHistory func(p0 context.Context, p1 EthUint64, p2 string, p3 []float64) (EthFeeHistory, error) `perm:"read"` + EthFeeHistory func(p0 context.Context, p1 eth.EthUint64, p2 string, p3 []float64) (eth.EthFeeHistory, error) `perm:"read"` - EthGasPrice func(p0 context.Context) (EthBigInt, error) `perm:"read"` + EthGasPrice func(p0 context.Context) (eth.EthBigInt, error) `perm:"read"` - EthGetBalance func(p0 context.Context, p1 EthAddress, p2 string) (EthBigInt, error) `perm:"read"` + EthGetBalance func(p0 context.Context, p1 eth.EthAddress, p2 string) (eth.EthBigInt, error) `perm:"read"` - EthGetBlockByHash func(p0 context.Context, p1 EthHash, p2 bool) (EthBlock, error) `perm:"read"` + EthGetBlockByHash func(p0 context.Context, p1 eth.EthHash, p2 bool) (eth.EthBlock, error) `perm:"read"` - EthGetBlockByNumber func(p0 context.Context, p1 string, p2 bool) (EthBlock, error) `perm:"read"` + EthGetBlockByNumber func(p0 context.Context, p1 string, p2 bool) (eth.EthBlock, error) `perm:"read"` - EthGetBlockTransactionCountByHash func(p0 context.Context, p1 EthHash) (EthUint64, error) `perm:"read"` + EthGetBlockTransactionCountByHash func(p0 context.Context, p1 eth.EthHash) (eth.EthUint64, error) `perm:"read"` - EthGetBlockTransactionCountByNumber func(p0 context.Context, p1 EthUint64) (EthUint64, error) `perm:"read"` + EthGetBlockTransactionCountByNumber func(p0 context.Context, p1 eth.EthUint64) (eth.EthUint64, error) `perm:"read"` - EthGetCode func(p0 context.Context, p1 EthAddress, p2 string) (EthBytes, error) `perm:"read"` + EthGetCode func(p0 context.Context, p1 eth.EthAddress, p2 string) (eth.EthBytes, error) `perm:"read"` - EthGetStorageAt func(p0 context.Context, p1 EthAddress, p2 EthBytes, p3 string) (EthBytes, error) `perm:"read"` + EthGetStorageAt func(p0 context.Context, p1 eth.EthAddress, p2 eth.EthBytes, p3 string) (eth.EthBytes, error) `perm:"read"` - EthGetTransactionByBlockHashAndIndex func(p0 context.Context, p1 EthHash, p2 EthUint64) (EthTx, error) `perm:"read"` + EthGetTransactionByBlockHashAndIndex func(p0 context.Context, p1 eth.EthHash, p2 eth.EthUint64) (eth.EthTx, error) `perm:"read"` - EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 EthUint64, p2 EthUint64) (EthTx, error) `perm:"read"` + EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 eth.EthUint64, p2 eth.EthUint64) (eth.EthTx, error) `perm:"read"` - EthGetTransactionByHash func(p0 context.Context, p1 *EthHash) (*EthTx, error) `perm:"read"` + EthGetTransactionByHash func(p0 context.Context, p1 *eth.EthHash) (*eth.EthTx, error) `perm:"read"` - EthGetTransactionCount func(p0 context.Context, p1 EthAddress, p2 string) (EthUint64, error) `perm:"read"` + EthGetTransactionCount func(p0 context.Context, p1 eth.EthAddress, p2 string) (eth.EthUint64, error) `perm:"read"` - EthGetTransactionReceipt func(p0 context.Context, p1 EthHash) (*EthTxReceipt, error) `perm:"read"` + EthGetTransactionReceipt func(p0 context.Context, p1 eth.EthHash) (*eth.EthTxReceipt, error) `perm:"read"` - EthMaxPriorityFeePerGas func(p0 context.Context) (EthBigInt, error) `perm:"read"` + EthMaxPriorityFeePerGas func(p0 context.Context) (eth.EthBigInt, error) `perm:"read"` - EthProtocolVersion func(p0 context.Context) (EthUint64, error) `perm:"read"` + EthProtocolVersion func(p0 context.Context) (eth.EthUint64, error) `perm:"read"` - EthSendRawTransaction func(p0 context.Context, p1 EthBytes) (EthHash, error) `perm:"read"` + EthSendRawTransaction func(p0 context.Context, p1 eth.EthBytes) (eth.EthHash, error) `perm:"read"` GasEstimateFeeCap func(p0 context.Context, p1 *types.Message, p2 int64, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` @@ -1844,246 +1844,246 @@ func (s *FullNodeStub) CreateBackup(p0 context.Context, p1 string) error { return ErrNotSupported } -func (s *FullNodeStruct) EthAccounts(p0 context.Context) ([]EthAddress, error) { +func (s *FullNodeStruct) EthAccounts(p0 context.Context) ([]eth.EthAddress, error) { if s.Internal.EthAccounts == nil { - return *new([]EthAddress), ErrNotSupported + return *new([]eth.EthAddress), ErrNotSupported } return s.Internal.EthAccounts(p0) } -func (s *FullNodeStub) EthAccounts(p0 context.Context) ([]EthAddress, error) { - return *new([]EthAddress), ErrNotSupported +func (s *FullNodeStub) EthAccounts(p0 context.Context) ([]eth.EthAddress, error) { + return *new([]eth.EthAddress), ErrNotSupported } -func (s *FullNodeStruct) EthBlockNumber(p0 context.Context) (EthUint64, error) { +func (s *FullNodeStruct) EthBlockNumber(p0 context.Context) (eth.EthUint64, error) { if s.Internal.EthBlockNumber == nil { - return *new(EthUint64), ErrNotSupported + return *new(eth.EthUint64), ErrNotSupported } return s.Internal.EthBlockNumber(p0) } -func (s *FullNodeStub) EthBlockNumber(p0 context.Context) (EthUint64, error) { - return *new(EthUint64), ErrNotSupported +func (s *FullNodeStub) EthBlockNumber(p0 context.Context) (eth.EthUint64, error) { + return *new(eth.EthUint64), ErrNotSupported } -func (s *FullNodeStruct) EthCall(p0 context.Context, p1 EthCall, p2 string) (EthBytes, error) { +func (s *FullNodeStruct) EthCall(p0 context.Context, p1 eth.EthCall, p2 string) (eth.EthBytes, error) { if s.Internal.EthCall == nil { - return *new(EthBytes), ErrNotSupported + return *new(eth.EthBytes), ErrNotSupported } return s.Internal.EthCall(p0, p1, p2) } -func (s *FullNodeStub) EthCall(p0 context.Context, p1 EthCall, p2 string) (EthBytes, error) { - return *new(EthBytes), ErrNotSupported +func (s *FullNodeStub) EthCall(p0 context.Context, p1 eth.EthCall, p2 string) (eth.EthBytes, error) { + return *new(eth.EthBytes), ErrNotSupported } -func (s *FullNodeStruct) EthChainId(p0 context.Context) (EthUint64, error) { +func (s *FullNodeStruct) EthChainId(p0 context.Context) (eth.EthUint64, error) { if s.Internal.EthChainId == nil { - return *new(EthUint64), ErrNotSupported + return *new(eth.EthUint64), ErrNotSupported } return s.Internal.EthChainId(p0) } -func (s *FullNodeStub) EthChainId(p0 context.Context) (EthUint64, error) { - return *new(EthUint64), ErrNotSupported +func (s *FullNodeStub) EthChainId(p0 context.Context) (eth.EthUint64, error) { + return *new(eth.EthUint64), ErrNotSupported } -func (s *FullNodeStruct) EthEstimateGas(p0 context.Context, p1 EthCall) (EthUint64, error) { +func (s *FullNodeStruct) EthEstimateGas(p0 context.Context, p1 eth.EthCall) (eth.EthUint64, error) { if s.Internal.EthEstimateGas == nil { - return *new(EthUint64), ErrNotSupported + return *new(eth.EthUint64), ErrNotSupported } return s.Internal.EthEstimateGas(p0, p1) } -func (s *FullNodeStub) EthEstimateGas(p0 context.Context, p1 EthCall) (EthUint64, error) { - return *new(EthUint64), ErrNotSupported +func (s *FullNodeStub) EthEstimateGas(p0 context.Context, p1 eth.EthCall) (eth.EthUint64, error) { + return *new(eth.EthUint64), ErrNotSupported } -func (s *FullNodeStruct) EthFeeHistory(p0 context.Context, p1 EthUint64, p2 string, p3 []float64) (EthFeeHistory, error) { +func (s *FullNodeStruct) EthFeeHistory(p0 context.Context, p1 eth.EthUint64, p2 string, p3 []float64) (eth.EthFeeHistory, error) { if s.Internal.EthFeeHistory == nil { - return *new(EthFeeHistory), ErrNotSupported + return *new(eth.EthFeeHistory), ErrNotSupported } return s.Internal.EthFeeHistory(p0, p1, p2, p3) } -func (s *FullNodeStub) EthFeeHistory(p0 context.Context, p1 EthUint64, p2 string, p3 []float64) (EthFeeHistory, error) { - return *new(EthFeeHistory), ErrNotSupported +func (s *FullNodeStub) EthFeeHistory(p0 context.Context, p1 eth.EthUint64, p2 string, p3 []float64) (eth.EthFeeHistory, error) { + return *new(eth.EthFeeHistory), ErrNotSupported } -func (s *FullNodeStruct) EthGasPrice(p0 context.Context) (EthBigInt, error) { +func (s *FullNodeStruct) EthGasPrice(p0 context.Context) (eth.EthBigInt, error) { if s.Internal.EthGasPrice == nil { - return *new(EthBigInt), ErrNotSupported + return *new(eth.EthBigInt), ErrNotSupported } return s.Internal.EthGasPrice(p0) } -func (s *FullNodeStub) EthGasPrice(p0 context.Context) (EthBigInt, error) { - return *new(EthBigInt), ErrNotSupported +func (s *FullNodeStub) EthGasPrice(p0 context.Context) (eth.EthBigInt, error) { + return *new(eth.EthBigInt), ErrNotSupported } -func (s *FullNodeStruct) EthGetBalance(p0 context.Context, p1 EthAddress, p2 string) (EthBigInt, error) { +func (s *FullNodeStruct) EthGetBalance(p0 context.Context, p1 eth.EthAddress, p2 string) (eth.EthBigInt, error) { if s.Internal.EthGetBalance == nil { - return *new(EthBigInt), ErrNotSupported + return *new(eth.EthBigInt), ErrNotSupported } return s.Internal.EthGetBalance(p0, p1, p2) } -func (s *FullNodeStub) EthGetBalance(p0 context.Context, p1 EthAddress, p2 string) (EthBigInt, error) { - return *new(EthBigInt), ErrNotSupported +func (s *FullNodeStub) EthGetBalance(p0 context.Context, p1 eth.EthAddress, p2 string) (eth.EthBigInt, error) { + return *new(eth.EthBigInt), ErrNotSupported } -func (s *FullNodeStruct) EthGetBlockByHash(p0 context.Context, p1 EthHash, p2 bool) (EthBlock, error) { +func (s *FullNodeStruct) EthGetBlockByHash(p0 context.Context, p1 eth.EthHash, p2 bool) (eth.EthBlock, error) { if s.Internal.EthGetBlockByHash == nil { - return *new(EthBlock), ErrNotSupported + return *new(eth.EthBlock), ErrNotSupported } return s.Internal.EthGetBlockByHash(p0, p1, p2) } -func (s *FullNodeStub) EthGetBlockByHash(p0 context.Context, p1 EthHash, p2 bool) (EthBlock, error) { - return *new(EthBlock), ErrNotSupported +func (s *FullNodeStub) EthGetBlockByHash(p0 context.Context, p1 eth.EthHash, p2 bool) (eth.EthBlock, error) { + return *new(eth.EthBlock), ErrNotSupported } -func (s *FullNodeStruct) EthGetBlockByNumber(p0 context.Context, p1 string, p2 bool) (EthBlock, error) { +func (s *FullNodeStruct) EthGetBlockByNumber(p0 context.Context, p1 string, p2 bool) (eth.EthBlock, error) { if s.Internal.EthGetBlockByNumber == nil { - return *new(EthBlock), ErrNotSupported + return *new(eth.EthBlock), ErrNotSupported } return s.Internal.EthGetBlockByNumber(p0, p1, p2) } -func (s *FullNodeStub) EthGetBlockByNumber(p0 context.Context, p1 string, p2 bool) (EthBlock, error) { - return *new(EthBlock), ErrNotSupported +func (s *FullNodeStub) EthGetBlockByNumber(p0 context.Context, p1 string, p2 bool) (eth.EthBlock, error) { + return *new(eth.EthBlock), ErrNotSupported } -func (s *FullNodeStruct) EthGetBlockTransactionCountByHash(p0 context.Context, p1 EthHash) (EthUint64, error) { +func (s *FullNodeStruct) EthGetBlockTransactionCountByHash(p0 context.Context, p1 eth.EthHash) (eth.EthUint64, error) { if s.Internal.EthGetBlockTransactionCountByHash == nil { - return *new(EthUint64), ErrNotSupported + return *new(eth.EthUint64), ErrNotSupported } return s.Internal.EthGetBlockTransactionCountByHash(p0, p1) } -func (s *FullNodeStub) EthGetBlockTransactionCountByHash(p0 context.Context, p1 EthHash) (EthUint64, error) { - return *new(EthUint64), ErrNotSupported +func (s *FullNodeStub) EthGetBlockTransactionCountByHash(p0 context.Context, p1 eth.EthHash) (eth.EthUint64, error) { + return *new(eth.EthUint64), ErrNotSupported } -func (s *FullNodeStruct) EthGetBlockTransactionCountByNumber(p0 context.Context, p1 EthUint64) (EthUint64, error) { +func (s *FullNodeStruct) EthGetBlockTransactionCountByNumber(p0 context.Context, p1 eth.EthUint64) (eth.EthUint64, error) { if s.Internal.EthGetBlockTransactionCountByNumber == nil { - return *new(EthUint64), ErrNotSupported + return *new(eth.EthUint64), ErrNotSupported } return s.Internal.EthGetBlockTransactionCountByNumber(p0, p1) } -func (s *FullNodeStub) EthGetBlockTransactionCountByNumber(p0 context.Context, p1 EthUint64) (EthUint64, error) { - return *new(EthUint64), ErrNotSupported +func (s *FullNodeStub) EthGetBlockTransactionCountByNumber(p0 context.Context, p1 eth.EthUint64) (eth.EthUint64, error) { + return *new(eth.EthUint64), ErrNotSupported } -func (s *FullNodeStruct) EthGetCode(p0 context.Context, p1 EthAddress, p2 string) (EthBytes, error) { +func (s *FullNodeStruct) EthGetCode(p0 context.Context, p1 eth.EthAddress, p2 string) (eth.EthBytes, error) { if s.Internal.EthGetCode == nil { - return *new(EthBytes), ErrNotSupported + return *new(eth.EthBytes), ErrNotSupported } return s.Internal.EthGetCode(p0, p1, p2) } -func (s *FullNodeStub) EthGetCode(p0 context.Context, p1 EthAddress, p2 string) (EthBytes, error) { - return *new(EthBytes), ErrNotSupported +func (s *FullNodeStub) EthGetCode(p0 context.Context, p1 eth.EthAddress, p2 string) (eth.EthBytes, error) { + return *new(eth.EthBytes), ErrNotSupported } -func (s *FullNodeStruct) EthGetStorageAt(p0 context.Context, p1 EthAddress, p2 EthBytes, p3 string) (EthBytes, error) { +func (s *FullNodeStruct) EthGetStorageAt(p0 context.Context, p1 eth.EthAddress, p2 eth.EthBytes, p3 string) (eth.EthBytes, error) { if s.Internal.EthGetStorageAt == nil { - return *new(EthBytes), ErrNotSupported + return *new(eth.EthBytes), ErrNotSupported } return s.Internal.EthGetStorageAt(p0, p1, p2, p3) } -func (s *FullNodeStub) EthGetStorageAt(p0 context.Context, p1 EthAddress, p2 EthBytes, p3 string) (EthBytes, error) { - return *new(EthBytes), ErrNotSupported +func (s *FullNodeStub) EthGetStorageAt(p0 context.Context, p1 eth.EthAddress, p2 eth.EthBytes, p3 string) (eth.EthBytes, error) { + return *new(eth.EthBytes), ErrNotSupported } -func (s *FullNodeStruct) EthGetTransactionByBlockHashAndIndex(p0 context.Context, p1 EthHash, p2 EthUint64) (EthTx, error) { +func (s *FullNodeStruct) EthGetTransactionByBlockHashAndIndex(p0 context.Context, p1 eth.EthHash, p2 eth.EthUint64) (eth.EthTx, error) { if s.Internal.EthGetTransactionByBlockHashAndIndex == nil { - return *new(EthTx), ErrNotSupported + return *new(eth.EthTx), ErrNotSupported } return s.Internal.EthGetTransactionByBlockHashAndIndex(p0, p1, p2) } -func (s *FullNodeStub) EthGetTransactionByBlockHashAndIndex(p0 context.Context, p1 EthHash, p2 EthUint64) (EthTx, error) { - return *new(EthTx), ErrNotSupported +func (s *FullNodeStub) EthGetTransactionByBlockHashAndIndex(p0 context.Context, p1 eth.EthHash, p2 eth.EthUint64) (eth.EthTx, error) { + return *new(eth.EthTx), ErrNotSupported } -func (s *FullNodeStruct) EthGetTransactionByBlockNumberAndIndex(p0 context.Context, p1 EthUint64, p2 EthUint64) (EthTx, error) { +func (s *FullNodeStruct) EthGetTransactionByBlockNumberAndIndex(p0 context.Context, p1 eth.EthUint64, p2 eth.EthUint64) (eth.EthTx, error) { if s.Internal.EthGetTransactionByBlockNumberAndIndex == nil { - return *new(EthTx), ErrNotSupported + return *new(eth.EthTx), ErrNotSupported } return s.Internal.EthGetTransactionByBlockNumberAndIndex(p0, p1, p2) } -func (s *FullNodeStub) EthGetTransactionByBlockNumberAndIndex(p0 context.Context, p1 EthUint64, p2 EthUint64) (EthTx, error) { - return *new(EthTx), ErrNotSupported +func (s *FullNodeStub) EthGetTransactionByBlockNumberAndIndex(p0 context.Context, p1 eth.EthUint64, p2 eth.EthUint64) (eth.EthTx, error) { + return *new(eth.EthTx), ErrNotSupported } -func (s *FullNodeStruct) EthGetTransactionByHash(p0 context.Context, p1 *EthHash) (*EthTx, error) { +func (s *FullNodeStruct) EthGetTransactionByHash(p0 context.Context, p1 *eth.EthHash) (*eth.EthTx, error) { if s.Internal.EthGetTransactionByHash == nil { return nil, ErrNotSupported } return s.Internal.EthGetTransactionByHash(p0, p1) } -func (s *FullNodeStub) EthGetTransactionByHash(p0 context.Context, p1 *EthHash) (*EthTx, error) { +func (s *FullNodeStub) EthGetTransactionByHash(p0 context.Context, p1 *eth.EthHash) (*eth.EthTx, error) { return nil, ErrNotSupported } -func (s *FullNodeStruct) EthGetTransactionCount(p0 context.Context, p1 EthAddress, p2 string) (EthUint64, error) { +func (s *FullNodeStruct) EthGetTransactionCount(p0 context.Context, p1 eth.EthAddress, p2 string) (eth.EthUint64, error) { if s.Internal.EthGetTransactionCount == nil { - return *new(EthUint64), ErrNotSupported + return *new(eth.EthUint64), ErrNotSupported } return s.Internal.EthGetTransactionCount(p0, p1, p2) } -func (s *FullNodeStub) EthGetTransactionCount(p0 context.Context, p1 EthAddress, p2 string) (EthUint64, error) { - return *new(EthUint64), ErrNotSupported +func (s *FullNodeStub) EthGetTransactionCount(p0 context.Context, p1 eth.EthAddress, p2 string) (eth.EthUint64, error) { + return *new(eth.EthUint64), ErrNotSupported } -func (s *FullNodeStruct) EthGetTransactionReceipt(p0 context.Context, p1 EthHash) (*EthTxReceipt, error) { +func (s *FullNodeStruct) EthGetTransactionReceipt(p0 context.Context, p1 eth.EthHash) (*eth.EthTxReceipt, error) { if s.Internal.EthGetTransactionReceipt == nil { return nil, ErrNotSupported } return s.Internal.EthGetTransactionReceipt(p0, p1) } -func (s *FullNodeStub) EthGetTransactionReceipt(p0 context.Context, p1 EthHash) (*EthTxReceipt, error) { +func (s *FullNodeStub) EthGetTransactionReceipt(p0 context.Context, p1 eth.EthHash) (*eth.EthTxReceipt, error) { return nil, ErrNotSupported } -func (s *FullNodeStruct) EthMaxPriorityFeePerGas(p0 context.Context) (EthBigInt, error) { +func (s *FullNodeStruct) EthMaxPriorityFeePerGas(p0 context.Context) (eth.EthBigInt, error) { if s.Internal.EthMaxPriorityFeePerGas == nil { - return *new(EthBigInt), ErrNotSupported + return *new(eth.EthBigInt), ErrNotSupported } return s.Internal.EthMaxPriorityFeePerGas(p0) } -func (s *FullNodeStub) EthMaxPriorityFeePerGas(p0 context.Context) (EthBigInt, error) { - return *new(EthBigInt), ErrNotSupported +func (s *FullNodeStub) EthMaxPriorityFeePerGas(p0 context.Context) (eth.EthBigInt, error) { + return *new(eth.EthBigInt), ErrNotSupported } -func (s *FullNodeStruct) EthProtocolVersion(p0 context.Context) (EthUint64, error) { +func (s *FullNodeStruct) EthProtocolVersion(p0 context.Context) (eth.EthUint64, error) { if s.Internal.EthProtocolVersion == nil { - return *new(EthUint64), ErrNotSupported + return *new(eth.EthUint64), ErrNotSupported } return s.Internal.EthProtocolVersion(p0) } -func (s *FullNodeStub) EthProtocolVersion(p0 context.Context) (EthUint64, error) { - return *new(EthUint64), ErrNotSupported +func (s *FullNodeStub) EthProtocolVersion(p0 context.Context) (eth.EthUint64, error) { + return *new(eth.EthUint64), ErrNotSupported } -func (s *FullNodeStruct) EthSendRawTransaction(p0 context.Context, p1 EthBytes) (EthHash, error) { +func (s *FullNodeStruct) EthSendRawTransaction(p0 context.Context, p1 eth.EthBytes) (eth.EthHash, error) { if s.Internal.EthSendRawTransaction == nil { - return *new(EthHash), ErrNotSupported + return *new(eth.EthHash), ErrNotSupported } return s.Internal.EthSendRawTransaction(p0, p1) } -func (s *FullNodeStub) EthSendRawTransaction(p0 context.Context, p1 EthBytes) (EthHash, error) { - return *new(EthHash), ErrNotSupported +func (s *FullNodeStub) EthSendRawTransaction(p0 context.Context, p1 eth.EthBytes) (eth.EthHash, error) { + return *new(eth.EthHash), ErrNotSupported } func (s *FullNodeStruct) GasEstimateFeeCap(p0 context.Context, p1 *types.Message, p2 int64, p3 types.TipSetKey) (types.BigInt, error) { diff --git a/chain/consensus/filcns/filecoin.go b/chain/consensus/filcns/filecoin.go index 57041005226..c2cc3aa83d3 100644 --- a/chain/consensus/filcns/filecoin.go +++ b/chain/consensus/filcns/filecoin.go @@ -28,7 +28,6 @@ import ( blockadt "github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof" - "github.com/filecoin-project/lotus/api" bstore "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain" @@ -36,6 +35,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors/builtin/power" "github.com/filecoin-project/lotus/chain/beacon" "github.com/filecoin-project/lotus/chain/consensus" + "github.com/filecoin-project/lotus/chain/eth" "github.com/filecoin-project/lotus/chain/rand" "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/stmgr" @@ -577,7 +577,7 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl digest := m.Message.Cid().Bytes() if m.Signature.Type == crypto.SigTypeDelegated { - txArgs, err := api.NewEthTxArgsFromMessage(&m.Message) + txArgs, err := eth.NewEthTxArgsFromMessage(&m.Message) if err != nil { return err } diff --git a/api/eth_transactions.go b/chain/eth/eth_transactions.go similarity index 99% rename from api/eth_transactions.go rename to chain/eth/eth_transactions.go index ee2b083ceb4..da294e95ce3 100644 --- a/api/eth_transactions.go +++ b/chain/eth/eth_transactions.go @@ -1,4 +1,4 @@ -package api +package eth import ( "bytes" diff --git a/api/eth_transactions_test.go b/chain/eth/eth_transactions_test.go similarity index 99% rename from api/eth_transactions_test.go rename to chain/eth/eth_transactions_test.go index e7dd6ba1e54..1bb93c2303c 100644 --- a/api/eth_transactions_test.go +++ b/chain/eth/eth_transactions_test.go @@ -1,4 +1,4 @@ -package api +package eth import ( "bytes" diff --git a/api/eth_types.go b/chain/eth/eth_types.go similarity index 99% rename from api/eth_types.go rename to chain/eth/eth_types.go index 1a8f38cc33a..323f83ad174 100644 --- a/api/eth_types.go +++ b/chain/eth/eth_types.go @@ -1,4 +1,4 @@ -package api +package eth import ( "bytes" diff --git a/api/eth_types_test.go b/chain/eth/eth_types_test.go similarity index 99% rename from api/eth_types_test.go rename to chain/eth/eth_types_test.go index d3c16d434a6..1725be444d6 100644 --- a/api/eth_types_test.go +++ b/chain/eth/eth_types_test.go @@ -1,5 +1,5 @@ // stm: #unit -package api +package eth import ( "strings" diff --git a/api/rlp.go b/chain/eth/rlp.go similarity index 99% rename from api/rlp.go rename to chain/eth/rlp.go index 1a0b06a804c..637b11e2b02 100644 --- a/api/rlp.go +++ b/chain/eth/rlp.go @@ -1,4 +1,4 @@ -package api +package eth import ( "bytes" diff --git a/api/rlp_test.go b/chain/eth/rlp_test.go similarity index 99% rename from api/rlp_test.go rename to chain/eth/rlp_test.go index fae14c7822a..2cb4afdebc0 100644 --- a/api/rlp_test.go +++ b/chain/eth/rlp_test.go @@ -1,4 +1,4 @@ -package api +package eth import ( "encoding/hex" diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 93f6977b156..c64813078bb 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -34,6 +34,7 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/eth" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" @@ -776,7 +777,7 @@ func sigCacheKey(m *types.SignedMessage) (string, error) { case crypto.SigTypeSecp256k1: return string(m.Cid().Bytes()), nil case crypto.SigTypeDelegated: - txArgs, err := api.NewEthTxArgsFromMessage(&m.Message) + txArgs, err := eth.NewEthTxArgsFromMessage(&m.Message) if err != nil { return "", err } @@ -803,7 +804,7 @@ func (mp *MessagePool) VerifyMsgSig(m *types.SignedMessage) error { } if m.Signature.Type == crypto.SigTypeDelegated { - txArgs, err := api.NewEthTxArgsFromMessage(&m.Message) + txArgs, err := eth.NewEthTxArgsFromMessage(&m.Message) if err != nil { return err } diff --git a/node/impl/full/dummy.go b/node/impl/full/dummy.go index a4669034023..912b5040290 100644 --- a/node/impl/full/dummy.go +++ b/node/impl/full/dummy.go @@ -4,74 +4,74 @@ import ( "context" "errors" - "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/eth" ) var ErrImplementMe = errors.New("Not implemented yet") type EthModuleDummy struct{} -func (e *EthModuleDummy) EthBlockNumber(ctx context.Context) (api.EthUint64, error) { +func (e *EthModuleDummy) EthBlockNumber(ctx context.Context) (eth.EthUint64, error) { return 0, ErrImplementMe } -func (e *EthModuleDummy) EthAccounts(ctx context.Context) ([]api.EthAddress, error) { +func (e *EthModuleDummy) EthAccounts(ctx context.Context) ([]eth.EthAddress, error) { return nil, ErrImplementMe } -func (e *EthModuleDummy) EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum api.EthUint64) (api.EthUint64, error) { +func (e *EthModuleDummy) EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum eth.EthUint64) (eth.EthUint64, error) { return 0, ErrImplementMe } -func (e *EthModuleDummy) EthGetBlockTransactionCountByHash(ctx context.Context, blkHash api.EthHash) (api.EthUint64, error) { +func (e *EthModuleDummy) EthGetBlockTransactionCountByHash(ctx context.Context, blkHash eth.EthHash) (eth.EthUint64, error) { return 0, ErrImplementMe } -func (e *EthModuleDummy) EthGetBlockByHash(ctx context.Context, blkHash api.EthHash, fullTxInfo bool) (api.EthBlock, error) { - return api.EthBlock{}, ErrImplementMe +func (e *EthModuleDummy) EthGetBlockByHash(ctx context.Context, blkHash eth.EthHash, fullTxInfo bool) (eth.EthBlock, error) { + return eth.EthBlock{}, ErrImplementMe } -func (e *EthModuleDummy) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (api.EthBlock, error) { - return api.EthBlock{}, ErrImplementMe +func (e *EthModuleDummy) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (eth.EthBlock, error) { + return eth.EthBlock{}, ErrImplementMe } -func (e *EthModuleDummy) EthGetTransactionByHash(ctx context.Context, txHash *api.EthHash) (*api.EthTx, error) { +func (e *EthModuleDummy) EthGetTransactionByHash(ctx context.Context, txHash *eth.EthHash) (*eth.EthTx, error) { return nil, ErrImplementMe } -func (e *EthModuleDummy) EthGetTransactionCount(ctx context.Context, sender api.EthAddress, blkOpt string) (api.EthUint64, error) { +func (e *EthModuleDummy) EthGetTransactionCount(ctx context.Context, sender eth.EthAddress, blkOpt string) (eth.EthUint64, error) { return 0, ErrImplementMe } -func (e *EthModuleDummy) EthGetTransactionReceipt(ctx context.Context, txHash api.EthHash) (*api.EthTxReceipt, error) { +func (e *EthModuleDummy) EthGetTransactionReceipt(ctx context.Context, txHash eth.EthHash) (*eth.EthTxReceipt, error) { return nil, ErrImplementMe } -func (e *EthModuleDummy) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash api.EthHash, txIndex api.EthUint64) (api.EthTx, error) { - return api.EthTx{}, ErrImplementMe +func (e *EthModuleDummy) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash eth.EthHash, txIndex eth.EthUint64) (eth.EthTx, error) { + return eth.EthTx{}, ErrImplementMe } -func (e *EthModuleDummy) EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum api.EthUint64, txIndex api.EthUint64) (api.EthTx, error) { - return api.EthTx{}, ErrImplementMe +func (e *EthModuleDummy) EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum eth.EthUint64, txIndex eth.EthUint64) (eth.EthTx, error) { + return eth.EthTx{}, ErrImplementMe } -func (e *EthModuleDummy) EthGetCode(ctx context.Context, address api.EthAddress, blkOpt string) (api.EthBytes, error) { +func (e *EthModuleDummy) EthGetCode(ctx context.Context, address eth.EthAddress, blkOpt string) (eth.EthBytes, error) { return nil, ErrImplementMe } -func (e *EthModuleDummy) EthGetStorageAt(ctx context.Context, address api.EthAddress, position api.EthBytes, blkParam string) (api.EthBytes, error) { +func (e *EthModuleDummy) EthGetStorageAt(ctx context.Context, address eth.EthAddress, position eth.EthBytes, blkParam string) (eth.EthBytes, error) { return nil, ErrImplementMe } -func (e *EthModuleDummy) EthGetBalance(ctx context.Context, address api.EthAddress, blkParam string) (api.EthBigInt, error) { - return api.EthBigIntZero, ErrImplementMe +func (e *EthModuleDummy) EthGetBalance(ctx context.Context, address eth.EthAddress, blkParam string) (eth.EthBigInt, error) { + return eth.EthBigIntZero, ErrImplementMe } -func (e *EthModuleDummy) EthFeeHistory(ctx context.Context, blkCount api.EthUint64, newestBlk string, rewardPercentiles []float64) (api.EthFeeHistory, error) { - return api.EthFeeHistory{}, ErrImplementMe +func (e *EthModuleDummy) EthFeeHistory(ctx context.Context, blkCount eth.EthUint64, newestBlk string, rewardPercentiles []float64) (eth.EthFeeHistory, error) { + return eth.EthFeeHistory{}, ErrImplementMe } -func (e *EthModuleDummy) EthChainId(ctx context.Context) (api.EthUint64, error) { +func (e *EthModuleDummy) EthChainId(ctx context.Context) (eth.EthUint64, error) { return 0, ErrImplementMe } @@ -83,26 +83,26 @@ func (e *EthModuleDummy) NetListening(ctx context.Context) (bool, error) { return false, ErrImplementMe } -func (e *EthModuleDummy) EthProtocolVersion(ctx context.Context) (api.EthUint64, error) { +func (e *EthModuleDummy) EthProtocolVersion(ctx context.Context) (eth.EthUint64, error) { return 0, ErrImplementMe } -func (e *EthModuleDummy) EthGasPrice(ctx context.Context) (api.EthBigInt, error) { - return api.EthBigIntZero, ErrImplementMe +func (e *EthModuleDummy) EthGasPrice(ctx context.Context) (eth.EthBigInt, error) { + return eth.EthBigIntZero, ErrImplementMe } -func (e *EthModuleDummy) EthEstimateGas(ctx context.Context, tx api.EthCall) (api.EthUint64, error) { +func (e *EthModuleDummy) EthEstimateGas(ctx context.Context, tx eth.EthCall) (eth.EthUint64, error) { return 0, ErrImplementMe } -func (e *EthModuleDummy) EthCall(ctx context.Context, tx api.EthCall, blkParam string) (api.EthBytes, error) { +func (e *EthModuleDummy) EthCall(ctx context.Context, tx eth.EthCall, blkParam string) (eth.EthBytes, error) { return nil, ErrImplementMe } -func (e *EthModuleDummy) EthMaxPriorityFeePerGas(ctx context.Context) (api.EthBigInt, error) { - return api.EthBigIntZero, ErrImplementMe +func (e *EthModuleDummy) EthMaxPriorityFeePerGas(ctx context.Context) (eth.EthBigInt, error) { + return eth.EthBigIntZero, ErrImplementMe } -func (e *EthModuleDummy) EthSendRawTransaction(ctx context.Context, rawTx api.EthBytes) (api.EthHash, error) { - return api.EthHash{}, ErrImplementMe +func (e *EthModuleDummy) EthSendRawTransaction(ctx context.Context, rawTx eth.EthBytes) (eth.EthHash, error) { + return eth.EthHash{}, ErrImplementMe } diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index a4be48a1549..0e4fe9be179 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -22,6 +22,7 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/eth" "github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" @@ -30,30 +31,30 @@ import ( ) type EthModuleAPI interface { - EthBlockNumber(ctx context.Context) (api.EthUint64, error) - EthAccounts(ctx context.Context) ([]api.EthAddress, error) - EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum api.EthUint64) (api.EthUint64, error) - EthGetBlockTransactionCountByHash(ctx context.Context, blkHash api.EthHash) (api.EthUint64, error) - EthGetBlockByHash(ctx context.Context, blkHash api.EthHash, fullTxInfo bool) (api.EthBlock, error) - EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (api.EthBlock, error) - EthGetTransactionByHash(ctx context.Context, txHash *api.EthHash) (*api.EthTx, error) - EthGetTransactionCount(ctx context.Context, sender api.EthAddress, blkOpt string) (api.EthUint64, error) - EthGetTransactionReceipt(ctx context.Context, txHash api.EthHash) (*api.EthTxReceipt, error) - EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash api.EthHash, txIndex api.EthUint64) (api.EthTx, error) - EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum api.EthUint64, txIndex api.EthUint64) (api.EthTx, error) - EthGetCode(ctx context.Context, address api.EthAddress, blkOpt string) (api.EthBytes, error) - EthGetStorageAt(ctx context.Context, address api.EthAddress, position api.EthBytes, blkParam string) (api.EthBytes, error) - EthGetBalance(ctx context.Context, address api.EthAddress, blkParam string) (api.EthBigInt, error) - EthFeeHistory(ctx context.Context, blkCount api.EthUint64, newestBlk string, rewardPercentiles []float64) (api.EthFeeHistory, error) - EthChainId(ctx context.Context) (api.EthUint64, error) + EthBlockNumber(ctx context.Context) (eth.EthUint64, error) + EthAccounts(ctx context.Context) ([]eth.EthAddress, error) + EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum eth.EthUint64) (eth.EthUint64, error) + EthGetBlockTransactionCountByHash(ctx context.Context, blkHash eth.EthHash) (eth.EthUint64, error) + EthGetBlockByHash(ctx context.Context, blkHash eth.EthHash, fullTxInfo bool) (eth.EthBlock, error) + EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (eth.EthBlock, error) + EthGetTransactionByHash(ctx context.Context, txHash *eth.EthHash) (*eth.EthTx, error) + EthGetTransactionCount(ctx context.Context, sender eth.EthAddress, blkOpt string) (eth.EthUint64, error) + EthGetTransactionReceipt(ctx context.Context, txHash eth.EthHash) (*eth.EthTxReceipt, error) + EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash eth.EthHash, txIndex eth.EthUint64) (eth.EthTx, error) + EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum eth.EthUint64, txIndex eth.EthUint64) (eth.EthTx, error) + EthGetCode(ctx context.Context, address eth.EthAddress, blkOpt string) (eth.EthBytes, error) + EthGetStorageAt(ctx context.Context, address eth.EthAddress, position eth.EthBytes, blkParam string) (eth.EthBytes, error) + EthGetBalance(ctx context.Context, address eth.EthAddress, blkParam string) (eth.EthBigInt, error) + EthFeeHistory(ctx context.Context, blkCount eth.EthUint64, newestBlk string, rewardPercentiles []float64) (eth.EthFeeHistory, error) + EthChainId(ctx context.Context) (eth.EthUint64, error) NetVersion(ctx context.Context) (string, error) NetListening(ctx context.Context) (bool, error) - EthProtocolVersion(ctx context.Context) (api.EthUint64, error) - EthGasPrice(ctx context.Context) (api.EthBigInt, error) - EthEstimateGas(ctx context.Context, tx api.EthCall) (api.EthUint64, error) - EthCall(ctx context.Context, tx api.EthCall, blkParam string) (api.EthBytes, error) - EthMaxPriorityFeePerGas(ctx context.Context) (api.EthBigInt, error) - EthSendRawTransaction(ctx context.Context, rawTx api.EthBytes) (api.EthHash, error) + EthProtocolVersion(ctx context.Context) (eth.EthUint64, error) + EthGasPrice(ctx context.Context) (eth.EthBigInt, error) + EthEstimateGas(ctx context.Context, tx eth.EthCall) (eth.EthUint64, error) + EthCall(ctx context.Context, tx eth.EthCall, blkParam string) (eth.EthBytes, error) + EthMaxPriorityFeePerGas(ctx context.Context) (eth.EthBigInt, error) + EthSendRawTransaction(ctx context.Context, rawTx eth.EthBytes) (eth.EthHash, error) } var _ EthModuleAPI = *new(api.FullNode) @@ -87,14 +88,14 @@ func (a *EthModule) StateNetworkName(ctx context.Context) (dtypes.NetworkName, e return stmgr.GetNetworkName(ctx, a.StateManager, a.Chain.GetHeaviestTipSet().ParentState()) } -func (a *EthModule) EthBlockNumber(context.Context) (api.EthUint64, error) { +func (a *EthModule) EthBlockNumber(context.Context) (eth.EthUint64, error) { height := a.Chain.GetHeaviestTipSet().Height() - return api.EthUint64(height), nil + return eth.EthUint64(height), nil } -func (a *EthModule) EthAccounts(context.Context) ([]api.EthAddress, error) { +func (a *EthModule) EthAccounts(context.Context) ([]eth.EthAddress, error) { // The lotus node is not expected to hold manage accounts, so we'll always return an empty array - return []api.EthAddress{}, nil + return []eth.EthAddress{}, nil } func (a *EthModule) countTipsetMsgs(ctx context.Context, ts *types.TipSet) (int, error) { @@ -111,54 +112,54 @@ func (a *EthModule) countTipsetMsgs(ctx context.Context, ts *types.TipSet) (int, return count, nil } -func (a *EthModule) EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum api.EthUint64) (api.EthUint64, error) { +func (a *EthModule) EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum eth.EthUint64) (eth.EthUint64, error) { ts, err := a.Chain.GetTipsetByHeight(ctx, abi.ChainEpoch(blkNum), nil, false) if err != nil { - return api.EthUint64(0), xerrors.Errorf("error loading tipset %s: %w", ts, err) + return eth.EthUint64(0), xerrors.Errorf("error loading tipset %s: %w", ts, err) } count, err := a.countTipsetMsgs(ctx, ts) - return api.EthUint64(count), err + return eth.EthUint64(count), err } -func (a *EthModule) EthGetBlockTransactionCountByHash(ctx context.Context, blkHash api.EthHash) (api.EthUint64, error) { +func (a *EthModule) EthGetBlockTransactionCountByHash(ctx context.Context, blkHash eth.EthHash) (eth.EthUint64, error) { ts, err := a.Chain.GetTipSetByCid(ctx, blkHash.ToCid()) if err != nil { - return api.EthUint64(0), xerrors.Errorf("error loading tipset %s: %w", ts, err) + return eth.EthUint64(0), xerrors.Errorf("error loading tipset %s: %w", ts, err) } count, err := a.countTipsetMsgs(ctx, ts) - return api.EthUint64(count), err + return eth.EthUint64(count), err } -func (a *EthModule) EthGetBlockByHash(ctx context.Context, blkHash api.EthHash, fullTxInfo bool) (api.EthBlock, error) { +func (a *EthModule) EthGetBlockByHash(ctx context.Context, blkHash eth.EthHash, fullTxInfo bool) (eth.EthBlock, error) { ts, err := a.Chain.GetTipSetByCid(ctx, blkHash.ToCid()) if err != nil { - return api.EthBlock{}, xerrors.Errorf("error loading tipset %s: %w", ts, err) + return eth.EthBlock{}, xerrors.Errorf("error loading tipset %s: %w", ts, err) } return a.newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo) } -func (a *EthModule) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (api.EthBlock, error) { - typ, num, err := api.ParseBlkNumOption(blkNum) +func (a *EthModule) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (eth.EthBlock, error) { + typ, num, err := eth.ParseBlkNumOption(blkNum) if err != nil { - return api.EthBlock{}, fmt.Errorf("cannot parse block number: %v", err) + return eth.EthBlock{}, fmt.Errorf("cannot parse block number: %v", err) } switch typ { - case api.BlkNumLatest: - num = api.EthUint64(a.Chain.GetHeaviestTipSet().Height()) - 1 - case api.BlkNumPending: - num = api.EthUint64(a.Chain.GetHeaviestTipSet().Height()) + case eth.BlkNumLatest: + num = eth.EthUint64(a.Chain.GetHeaviestTipSet().Height()) - 1 + case eth.BlkNumPending: + num = eth.EthUint64(a.Chain.GetHeaviestTipSet().Height()) } ts, err := a.Chain.GetTipsetByHeight(ctx, abi.ChainEpoch(num), nil, false) if err != nil { - return api.EthBlock{}, xerrors.Errorf("error loading tipset %s: %w", ts, err) + return eth.EthBlock{}, xerrors.Errorf("error loading tipset %s: %w", ts, err) } return a.newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo) } -func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *api.EthHash) (*api.EthTx, error) { +func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *eth.EthHash) (*eth.EthTx, error) { // Ethereum's behavior is to return null when the txHash is invalid, so we use nil to check if txHash is valid if txHash == nil { return nil, nil @@ -178,19 +179,19 @@ func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *api.Eth return &tx, nil } -func (a *EthModule) EthGetTransactionCount(ctx context.Context, sender api.EthAddress, blkParam string) (api.EthUint64, error) { +func (a *EthModule) EthGetTransactionCount(ctx context.Context, sender eth.EthAddress, blkParam string) (eth.EthUint64, error) { addr, err := sender.ToFilecoinAddress() if err != nil { - return api.EthUint64(0), nil + return eth.EthUint64(0), nil } nonce, err := a.Mpool.GetNonce(ctx, addr, types.EmptyTSK) if err != nil { - return api.EthUint64(0), nil + return eth.EthUint64(0), nil } - return api.EthUint64(nonce), nil + return eth.EthUint64(nonce), nil } -func (a *EthModule) EthGetTransactionReceipt(ctx context.Context, txHash api.EthHash) (*api.EthTxReceipt, error) { +func (a *EthModule) EthGetTransactionReceipt(ctx context.Context, txHash eth.EthHash) (*eth.EthTxReceipt, error) { cid := txHash.ToCid() msgLookup, err := a.StateAPI.StateSearchMsg(ctx, types.EmptyTSK, cid, api.LookbackNoLimit, true) @@ -208,23 +209,23 @@ func (a *EthModule) EthGetTransactionReceipt(ctx context.Context, txHash api.Eth return nil, nil } - receipt, err := api.NewEthTxReceipt(tx, msgLookup, replay) + receipt, err := eth.NewEthTxReceipt(tx, msgLookup, replay) if err != nil { return nil, nil } return &receipt, nil } -func (a *EthModule) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash api.EthHash, txIndex api.EthUint64) (api.EthTx, error) { - return api.EthTx{}, nil +func (a *EthModule) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash eth.EthHash, txIndex eth.EthUint64) (eth.EthTx, error) { + return eth.EthTx{}, nil } -func (a *EthModule) EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum api.EthUint64, txIndex api.EthUint64) (api.EthTx, error) { - return api.EthTx{}, nil +func (a *EthModule) EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum eth.EthUint64, txIndex eth.EthUint64) (eth.EthTx, error) { + return eth.EthTx{}, nil } // EthGetCode returns string value of the compiled bytecode -func (a *EthModule) EthGetCode(ctx context.Context, ethAddr api.EthAddress, blkOpt string) (api.EthBytes, error) { +func (a *EthModule) EthGetCode(ctx context.Context, ethAddr eth.EthAddress, blkOpt string) (eth.EthBytes, error) { to, err := ethAddr.ToFilecoinAddress() if err != nil { return nil, xerrors.Errorf("cannot get Filecoin address: %w", err) @@ -288,7 +289,7 @@ func (a *EthModule) EthGetCode(ctx context.Context, ethAddr api.EthAddress, blkO return blk.RawData(), nil } -func (a *EthModule) EthGetStorageAt(ctx context.Context, ethAddr api.EthAddress, position api.EthBytes, blkParam string) (api.EthBytes, error) { +func (a *EthModule) EthGetStorageAt(ctx context.Context, ethAddr eth.EthAddress, position eth.EthBytes, blkParam string) (eth.EthBytes, error) { l := len(position) if l > 32 { return nil, fmt.Errorf("supplied storage key is too long") @@ -362,35 +363,35 @@ func (a *EthModule) EthGetStorageAt(ctx context.Context, ethAddr api.EthAddress, return res.MsgRct.Return, nil } -func (a *EthModule) EthGetBalance(ctx context.Context, address api.EthAddress, blkParam string) (api.EthBigInt, error) { +func (a *EthModule) EthGetBalance(ctx context.Context, address eth.EthAddress, blkParam string) (eth.EthBigInt, error) { filAddr, err := address.ToFilecoinAddress() if err != nil { - return api.EthBigInt{}, err + return eth.EthBigInt{}, err } actor, err := a.StateGetActor(ctx, filAddr, types.EmptyTSK) if xerrors.Is(err, types.ErrActorNotFound) { - return api.EthBigIntZero, nil + return eth.EthBigIntZero, nil } else if err != nil { - return api.EthBigInt{}, err + return eth.EthBigInt{}, err } - return api.EthBigInt{Int: actor.Balance.Int}, nil + return eth.EthBigInt{Int: actor.Balance.Int}, nil } -func (a *EthModule) EthChainId(ctx context.Context) (api.EthUint64, error) { - return api.EthUint64(build.Eip155ChainId), nil +func (a *EthModule) EthChainId(ctx context.Context) (eth.EthUint64, error) { + return eth.EthUint64(build.Eip155ChainId), nil } -func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount api.EthUint64, newestBlkNum string, rewardPercentiles []float64) (api.EthFeeHistory, error) { +func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount eth.EthUint64, newestBlkNum string, rewardPercentiles []float64) (eth.EthFeeHistory, error) { if blkCount > 1024 { - return api.EthFeeHistory{}, fmt.Errorf("block count should be smaller than 1024") + return eth.EthFeeHistory{}, fmt.Errorf("block count should be smaller than 1024") } newestBlkHeight := uint64(a.Chain.GetHeaviestTipSet().Height()) // TODO https://github.com/filecoin-project/ref-fvm/issues/1016 - var blkNum api.EthUint64 + var blkNum eth.EthUint64 err := blkNum.UnmarshalJSON([]byte(`"` + newestBlkNum + `"`)) if err == nil && uint64(blkNum) < newestBlkHeight { newestBlkHeight = uint64(blkNum) @@ -405,13 +406,13 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount api.EthUint64, n ts, err := a.Chain.GetTipsetByHeight(ctx, abi.ChainEpoch(newestBlkHeight), nil, false) if err != nil { - return api.EthFeeHistory{}, fmt.Errorf("cannot load find block height: %v", newestBlkHeight) + return eth.EthFeeHistory{}, fmt.Errorf("cannot load find block height: %v", newestBlkHeight) } // FIXME: baseFeePerGas should include the next block after the newest of the returned range, because this // can be inferred from the newest block. we use the newest block's baseFeePerGas for now but need to fix it // In other words, due to deferred execution, we might not be returning the most useful value here for the client. - baseFeeArray := []api.EthBigInt{api.EthBigInt(ts.Blocks()[0].ParentBaseFee)} + baseFeeArray := []eth.EthBigInt{eth.EthBigInt(ts.Blocks()[0].ParentBaseFee)} gasUsedRatioArray := []float64{} for ts.Height() >= abi.ChainEpoch(oldestBlkHeight) { @@ -419,17 +420,17 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount api.EthUint64, n // totalize gas used in the tipset. block, err := a.newEthBlockFromFilecoinTipSet(ctx, ts, false) if err != nil { - return api.EthFeeHistory{}, fmt.Errorf("cannot create eth block: %v", err) + return eth.EthFeeHistory{}, fmt.Errorf("cannot create eth block: %v", err) } // both arrays should be reversed at the end - baseFeeArray = append(baseFeeArray, api.EthBigInt(ts.Blocks()[0].ParentBaseFee)) + baseFeeArray = append(baseFeeArray, eth.EthBigInt(ts.Blocks()[0].ParentBaseFee)) gasUsedRatioArray = append(gasUsedRatioArray, float64(block.GasUsed)/float64(build.BlockGasLimit)) parentTsKey := ts.Parents() ts, err = a.Chain.LoadTipSet(ctx, parentTsKey) if err != nil { - return api.EthFeeHistory{}, fmt.Errorf("cannot load tipset key: %v", parentTsKey) + return eth.EthFeeHistory{}, fmt.Errorf("cannot load tipset key: %v", parentTsKey) } } @@ -442,7 +443,7 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount api.EthUint64, n gasUsedRatioArray[i], gasUsedRatioArray[j] = gasUsedRatioArray[j], gasUsedRatioArray[i] } - return api.EthFeeHistory{ + return eth.EthFeeHistory{ OldestBlock: oldestBlkHeight, BaseFeePerGas: baseFeeArray, GasUsedRatio: gasUsedRatioArray, @@ -462,20 +463,20 @@ func (a *EthModule) NetListening(ctx context.Context) (bool, error) { return true, nil } -func (a *EthModule) EthProtocolVersion(ctx context.Context) (api.EthUint64, error) { +func (a *EthModule) EthProtocolVersion(ctx context.Context) (eth.EthUint64, error) { height := a.Chain.GetHeaviestTipSet().Height() - return api.EthUint64(a.StateManager.GetNetworkVersion(ctx, height)), nil + return eth.EthUint64(a.StateManager.GetNetworkVersion(ctx, height)), nil } -func (a *EthModule) EthMaxPriorityFeePerGas(ctx context.Context) (api.EthBigInt, error) { +func (a *EthModule) EthMaxPriorityFeePerGas(ctx context.Context) (eth.EthBigInt, error) { gasPremium, err := a.GasAPI.GasEstimateGasPremium(ctx, 0, builtin.SystemActorAddr, 10000, types.EmptyTSK) if err != nil { - return api.EthBigInt(big.Zero()), err + return eth.EthBigInt(big.Zero()), err } - return api.EthBigInt(gasPremium), nil + return eth.EthBigInt(gasPremium), nil } -func (a *EthModule) EthGasPrice(ctx context.Context) (api.EthBigInt, error) { +func (a *EthModule) EthGasPrice(ctx context.Context) (eth.EthBigInt, error) { // According to Geth's implementation, eth_gasPrice should return base + tip // Ref: https://github.com/ethereum/pm/issues/328#issuecomment-853234014 @@ -484,22 +485,22 @@ func (a *EthModule) EthGasPrice(ctx context.Context) (api.EthBigInt, error) { premium, err := a.EthMaxPriorityFeePerGas(ctx) if err != nil { - return api.EthBigInt(big.Zero()), nil + return eth.EthBigInt(big.Zero()), nil } gasPrice := big.Add(baseFee, big.Int(premium)) - return api.EthBigInt(gasPrice), nil + return eth.EthBigInt(gasPrice), nil } -func (a *EthModule) EthSendRawTransaction(ctx context.Context, rawTx api.EthBytes) (api.EthHash, error) { - txArgs, err := api.ParseEthTxArgs(rawTx) +func (a *EthModule) EthSendRawTransaction(ctx context.Context, rawTx eth.EthBytes) (eth.EthHash, error) { + txArgs, err := eth.ParseEthTxArgs(rawTx) if err != nil { - return api.EmptyEthHash, err + return eth.EmptyEthHash, err } smsg, err := txArgs.ToSignedMessage() if err != nil { - return api.EmptyEthHash, err + return eth.EmptyEthHash, err } _, err = a.StateAPI.StateGetActor(ctx, smsg.Message.To, types.EmptyTSK) @@ -511,17 +512,17 @@ func (a *EthModule) EthSendRawTransaction(ctx context.Context, rawTx api.EthByte cid, err := a.MpoolAPI.MpoolPush(ctx, smsg) if err != nil { - return api.EmptyEthHash, err + return eth.EmptyEthHash, err } - return api.NewEthHashFromCid(cid) + return eth.NewEthHashFromCid(cid) } -func (a *EthModule) ethCallToFilecoinMessage(ctx context.Context, tx api.EthCall) (*types.Message, error) { +func (a *EthModule) ethCallToFilecoinMessage(ctx context.Context, tx eth.EthCall) (*types.Message, error) { var err error var from address.Address if tx.From == nil { // Send from the filecoin "system" address. - from, err = (api.EthAddress{}).ToFilecoinAddress() + from, err = (eth.EthAddress{}).ToFilecoinAddress() if err != nil { return nil, fmt.Errorf("failed to construct the ethereum system address: %w", err) } @@ -611,10 +612,10 @@ func (a *EthModule) applyMessage(ctx context.Context, msg *types.Message) (res * return res, nil } -func (a *EthModule) EthEstimateGas(ctx context.Context, tx api.EthCall) (api.EthUint64, error) { +func (a *EthModule) EthEstimateGas(ctx context.Context, tx eth.EthCall) (eth.EthUint64, error) { msg, err := a.ethCallToFilecoinMessage(ctx, tx) if err != nil { - return api.EthUint64(0), err + return eth.EthUint64(0), err } // Set the gas limit to the zero sentinel value, which makes @@ -623,13 +624,13 @@ func (a *EthModule) EthEstimateGas(ctx context.Context, tx api.EthCall) (api.Eth msg, err = a.GasAPI.GasEstimateMessageGas(ctx, msg, nil, types.EmptyTSK) if err != nil { - return api.EthUint64(0), err + return eth.EthUint64(0), err } - return api.EthUint64(msg.GasLimit), nil + return eth.EthUint64(msg.GasLimit), nil } -func (a *EthModule) EthCall(ctx context.Context, tx api.EthCall, blkParam string) (api.EthBytes, error) { +func (a *EthModule) EthCall(ctx context.Context, tx eth.EthCall, blkParam string) (eth.EthBytes, error) { msg, err := a.ethCallToFilecoinMessage(ctx, tx) if err != nil { return nil, err @@ -642,38 +643,38 @@ func (a *EthModule) EthCall(ctx context.Context, tx api.EthCall, blkParam string if len(invokeResult.MsgRct.Return) > 0 { return cbg.ReadByteArray(bytes.NewReader(invokeResult.MsgRct.Return), uint64(len(invokeResult.MsgRct.Return))) } - return api.EthBytes{}, nil + return eth.EthBytes{}, nil } -func (a *EthModule) newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTxInfo bool) (api.EthBlock, error) { +func (a *EthModule) newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTxInfo bool) (eth.EthBlock, error) { parent, err := a.Chain.LoadTipSet(ctx, ts.Parents()) if err != nil { - return api.EthBlock{}, err + return eth.EthBlock{}, err } parentKeyCid, err := parent.Key().Cid() if err != nil { - return api.EthBlock{}, err + return eth.EthBlock{}, err } - parentBlkHash, err := api.NewEthHashFromCid(parentKeyCid) + parentBlkHash, err := eth.NewEthHashFromCid(parentKeyCid) if err != nil { - return api.EthBlock{}, err + return eth.EthBlock{}, err } blkCid, err := ts.Key().Cid() if err != nil { - return api.EthBlock{}, err + return eth.EthBlock{}, err } - blkHash, err := api.NewEthHashFromCid(blkCid) + blkHash, err := eth.NewEthHashFromCid(blkCid) if err != nil { - return api.EthBlock{}, err + return eth.EthBlock{}, err } blkMsgs, err := a.Chain.BlockMsgsForTipset(ctx, ts) if err != nil { - return api.EthBlock{}, xerrors.Errorf("error loading messages for tipset: %v: %w", ts, err) + return eth.EthBlock{}, xerrors.Errorf("error loading messages for tipset: %v: %w", ts, err) } - block := api.NewEthBlock() + block := eth.NewEthBlock() // this seems to be a very expensive way to get gasUsed of the block. may need to find an efficient way to do it gasUsed := int64(0) @@ -681,20 +682,20 @@ func (a *EthModule) newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types for _, msg := range append(blkMsg.BlsMessages, blkMsg.SecpkMessages...) { msgLookup, err := a.StateAPI.StateSearchMsg(ctx, types.EmptyTSK, msg.Cid(), api.LookbackNoLimit, true) if err != nil || msgLookup == nil { - return api.EthBlock{}, nil + return eth.EthBlock{}, nil } gasUsed += msgLookup.Receipt.GasUsed if fullTxInfo { tx, err := a.newEthTxFromFilecoinMessageLookup(ctx, msgLookup) if err != nil { - return api.EthBlock{}, nil + return eth.EthBlock{}, nil } block.Transactions = append(block.Transactions, tx) } else { - hash, err := api.NewEthHashFromCid(msg.Cid()) + hash, err := eth.NewEthHashFromCid(msg.Cid()) if err != nil { - return api.EthBlock{}, err + return eth.EthBlock{}, err } block.Transactions = append(block.Transactions, hash.String()) } @@ -702,11 +703,11 @@ func (a *EthModule) newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types } block.Hash = blkHash - block.Number = api.EthUint64(ts.Height()) + block.Number = eth.EthUint64(ts.Height()) block.ParentHash = parentBlkHash - block.Timestamp = api.EthUint64(ts.Blocks()[0].Timestamp) - block.BaseFeePerGas = api.EthBigInt{Int: ts.Blocks()[0].ParentBaseFee.Int} - block.GasUsed = api.EthUint64(gasUsed) + block.Timestamp = eth.EthUint64(ts.Blocks()[0].Timestamp) + block.BaseFeePerGas = eth.EthBigInt{Int: ts.Blocks()[0].ParentBaseFee.Int} + block.GasUsed = eth.EthUint64(gasUsed) return block, nil } @@ -718,10 +719,10 @@ func (a *EthModule) newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types // 3. Otherwise, we fall back to returning a masked ID Ethereum address. If the supplied address is an f0 address, we // use that ID to form the masked ID address. // 4. Otherwise, we fetch the actor's ID from the state tree and form the masked ID with it. -func (a *EthModule) lookupEthAddress(ctx context.Context, addr address.Address) (api.EthAddress, error) { +func (a *EthModule) lookupEthAddress(ctx context.Context, addr address.Address) (eth.EthAddress, error) { // Attempt to convert directly. - if ethAddr, ok, err := api.TryEthAddressFromFilecoinAddress(addr, false); err != nil { - return api.EthAddress{}, err + if ethAddr, ok, err := eth.TryEthAddressFromFilecoinAddress(addr, false); err != nil { + return eth.EthAddress{}, err } else if ok { return ethAddr, nil } @@ -729,19 +730,19 @@ func (a *EthModule) lookupEthAddress(ctx context.Context, addr address.Address) // Lookup on the target actor. actor, err := a.StateAPI.StateGetActor(ctx, addr, types.EmptyTSK) if err != nil { - return api.EthAddress{}, err + return eth.EthAddress{}, err } if actor.Address != nil { - if ethAddr, ok, err := api.TryEthAddressFromFilecoinAddress(*actor.Address, false); err != nil { - return api.EthAddress{}, err + if ethAddr, ok, err := eth.TryEthAddressFromFilecoinAddress(*actor.Address, false); err != nil { + return eth.EthAddress{}, err } else if ok { return ethAddr, nil } } // Check if we already have an ID addr, and use it if possible. - if ethAddr, ok, err := api.TryEthAddressFromFilecoinAddress(addr, true); err != nil { - return api.EthAddress{}, err + if ethAddr, ok, err := eth.TryEthAddressFromFilecoinAddress(addr, true); err != nil { + return eth.EthAddress{}, err } else if ok { return ethAddr, nil } @@ -749,42 +750,42 @@ func (a *EthModule) lookupEthAddress(ctx context.Context, addr address.Address) // Otherwise, resolve the ID addr. idAddr, err := a.StateAPI.StateLookupID(ctx, addr, types.EmptyTSK) if err != nil { - return api.EthAddress{}, err + return eth.EthAddress{}, err } - return api.EthAddressFromFilecoinAddress(idAddr) + return eth.EthAddressFromFilecoinAddress(idAddr) } -func (a *EthModule) newEthTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *types.MsgLookup) (api.EthTx, error) { +func (a *EthModule) newEthTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *types.MsgLookup) (eth.EthTx, error) { if msgLookup == nil { - return api.EthTx{}, fmt.Errorf("msg does not exist") + return eth.EthTx{}, fmt.Errorf("msg does not exist") } cid := msgLookup.Message - txHash, err := api.NewEthHashFromCid(cid) + txHash, err := eth.NewEthHashFromCid(cid) if err != nil { - return api.EthTx{}, err + return eth.EthTx{}, err } ts, err := a.Chain.LoadTipSet(ctx, msgLookup.TipSet) if err != nil { - return api.EthTx{}, err + return eth.EthTx{}, err } // This tx is located in the parent tipset parentTs, err := a.Chain.LoadTipSet(ctx, ts.Parents()) if err != nil { - return api.EthTx{}, err + return eth.EthTx{}, err } parentTsCid, err := parentTs.Key().Cid() if err != nil { - return api.EthTx{}, err + return eth.EthTx{}, err } // lookup the transactionIndex txIdx := -1 msgs, err := a.Chain.MessagesForTipset(ctx, parentTs) if err != nil { - return api.EthTx{}, err + return eth.EthTx{}, err } for i, msg := range msgs { if msg.Cid() == msgLookup.Message { @@ -792,27 +793,27 @@ func (a *EthModule) newEthTxFromFilecoinMessageLookup(ctx context.Context, msgLo } } if txIdx == -1 { - return api.EthTx{}, fmt.Errorf("cannot find the msg in the tipset") + return eth.EthTx{}, fmt.Errorf("cannot find the msg in the tipset") } - blkHash, err := api.NewEthHashFromCid(parentTsCid) + blkHash, err := eth.NewEthHashFromCid(parentTsCid) if err != nil { - return api.EthTx{}, err + return eth.EthTx{}, err } msg, err := a.ChainAPI.ChainGetMessage(ctx, msgLookup.Message) if err != nil { - return api.EthTx{}, err + return eth.EthTx{}, err } fromEthAddr, err := a.lookupEthAddress(ctx, msg.From) if err != nil { - return api.EthTx{}, err + return eth.EthTx{}, err } toEthAddr, err := a.lookupEthAddress(ctx, msg.To) if err != nil { - return api.EthTx{}, err + return eth.EthTx{}, err } toAddr := &toEthAddr @@ -833,7 +834,7 @@ func (a *EthModule) newEthTxFromFilecoinMessageLookup(ctx context.Context, msgLo input = params.Initcode } if err != nil { - return api.EthTx{}, err + return eth.EthTx{}, err } } // Otherwise, try to decode as a cbor byte array. @@ -844,22 +845,22 @@ func (a *EthModule) newEthTxFromFilecoinMessageLookup(ctx context.Context, msgLo } } - tx := api.EthTx{ - ChainID: api.EthUint64(build.Eip155ChainId), + tx := eth.EthTx{ + ChainID: eth.EthUint64(build.Eip155ChainId), Hash: txHash, BlockHash: blkHash, - BlockNumber: api.EthUint64(parentTs.Height()), + BlockNumber: eth.EthUint64(parentTs.Height()), From: fromEthAddr, To: toAddr, - Value: api.EthBigInt(msg.Value), - Type: api.EthUint64(2), - TransactionIndex: api.EthUint64(txIdx), - Gas: api.EthUint64(msg.GasLimit), - MaxFeePerGas: api.EthBigInt(msg.GasFeeCap), - MaxPriorityFeePerGas: api.EthBigInt(msg.GasPremium), - V: api.EthBytes{}, - R: api.EthBytes{}, - S: api.EthBytes{}, + Value: eth.EthBigInt(msg.Value), + Type: eth.EthUint64(2), + TransactionIndex: eth.EthUint64(txIdx), + Gas: eth.EthUint64(msg.GasLimit), + MaxFeePerGas: eth.EthBigInt(msg.GasFeeCap), + MaxPriorityFeePerGas: eth.EthBigInt(msg.GasPremium), + V: eth.EthBytes{}, + R: eth.EthBytes{}, + S: eth.EthBytes{}, Input: input, } return tx, nil