diff --git a/app/node/builder.go b/app/node/builder.go index efd20daccf..acc54f56fb 100644 --- a/app/node/builder.go +++ b/app/node/builder.go @@ -7,6 +7,7 @@ import ( "github.com/filecoin-project/venus/app/submodule/dagservice" "github.com/filecoin-project/venus/app/submodule/eth" + "github.com/filecoin-project/venus/app/submodule/f3" "github.com/filecoin-project/venus/app/submodule/network" "github.com/ipfs-force-community/sophon-auth/core" "github.com/ipfs-force-community/sophon-auth/jwtclient" @@ -136,6 +137,11 @@ func (b *Builder) build(ctx context.Context) (*Node, error) { return nil, errors.Wrap(err, "failed to build node.wallet") } + nd.f3, err = f3.NewF3Submodule(ctx, nd.repo, nd.chain, nd.network, nd.wallet.API()) + if err != nil { + return nil, errors.Wrap(err, "failed to build node.f3") + } + nd.mpool, err = mpool.NewMpoolSubmodule(ctx, (*builder)(b), nd.network, nd.chain, nd.wallet) if err != nil { return nil, errors.Wrap(err, "failed to build node.mpool") @@ -191,6 +197,7 @@ func (b *Builder) build(ctx context.Context) (*Node, error) { nd.common, nd.eth, nd.actorEvent, + nd.f3, ) if err != nil { diff --git a/app/node/env.go b/app/node/env.go index 1e7812f801..719d4fd76b 100644 --- a/app/node/env.go +++ b/app/node/env.go @@ -7,6 +7,7 @@ import ( "github.com/filecoin-project/venus/app/submodule/storagenetworking" v1api "github.com/filecoin-project/venus/venus-shared/api/chain/v1" + "github.com/filecoin-project/venus/venus-shared/api/f3" ) // Env is the environment for command API handlers. @@ -26,6 +27,7 @@ type Env struct { PaychAPI v1api.IPaychan CommonAPI v1api.ICommon EthAPI v1api.IETH + F3API f3.F3 } var _ cmds.Environment = (*Env)(nil) diff --git a/app/node/node.go b/app/node/node.go index e883120bc0..91e8b817f5 100644 --- a/app/node/node.go +++ b/app/node/node.go @@ -18,6 +18,7 @@ import ( configModule "github.com/filecoin-project/venus/app/submodule/config" "github.com/filecoin-project/venus/app/submodule/dagservice" "github.com/filecoin-project/venus/app/submodule/eth" + "github.com/filecoin-project/venus/app/submodule/f3" "github.com/filecoin-project/venus/app/submodule/market" "github.com/filecoin-project/venus/app/submodule/mining" "github.com/filecoin-project/venus/app/submodule/mpool" @@ -91,6 +92,7 @@ type Node struct { wallet *wallet.WalletSubmodule mpool *mpool.MessagePoolSubmodule storageNetworking *storagenetworking.StorageNetworkingSubmodule + f3 *f3.F3Submodule // paychannel and market market *market.MarketSubmodule @@ -378,6 +380,7 @@ func (node *Node) createServerEnv(ctx context.Context) *Env { MarketAPI: node.market.API(), CommonAPI: node.common, EthAPI: node.eth.API(), + F3API: node.f3.API(), } return &env diff --git a/app/submodule/f3/f3_api.go b/app/submodule/f3/f3_api.go new file mode 100644 index 0000000000..77216567f4 --- /dev/null +++ b/app/submodule/f3/f3_api.go @@ -0,0 +1,54 @@ +package f3 + +import ( + "context" + "errors" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-f3/certs" + "github.com/filecoin-project/venus/venus-shared/api/f3" + "golang.org/x/xerrors" +) + +var _ f3.F3 = &f3API{} + +type f3API struct { + f3module *F3Submodule +} + +var ErrF3Disabled = errors.New("f3 is disabled") + +func (f3api *f3API) F3Participate(ctx context.Context, miner address.Address) (<-chan string, error) { + + if f3api.f3module.F3 == nil { + log.Infof("F3Participate called for %v, F3 is disabled", miner) + return nil, ErrF3Disabled + } + + // Make channel with some buffer to avoid blocking under higher load. + errCh := make(chan string, 4) + log.Infof("starting F3 participation for %v", miner) + + actorID, err := address.IDFromAddress(miner) + if err != nil { + return nil, xerrors.Errorf("miner address in F3Participate not of ID type: %w", err) + } + + // Participate takes control of closing the channel + go f3api.f3module.F3.Participate(ctx, actorID, errCh) + return errCh, nil +} + +func (f3api *f3API) F3GetCertificate(ctx context.Context, instance uint64) (*certs.FinalityCertificate, error) { + if f3api.f3module.F3 == nil { + return nil, ErrF3Disabled + } + return f3api.f3module.F3.GetCert(ctx, instance) +} + +func (f3api *f3API) F3GetLatestCertificate(ctx context.Context) (*certs.FinalityCertificate, error) { + if f3api.f3module.F3 == nil { + return nil, ErrF3Disabled + } + return f3api.f3module.F3.GetLatestCert(ctx) +} diff --git a/app/submodule/f3/f3_submodule.go b/app/submodule/f3/f3_submodule.go new file mode 100644 index 0000000000..61b00626c8 --- /dev/null +++ b/app/submodule/f3/f3_submodule.go @@ -0,0 +1,55 @@ +package f3 + +import ( + "context" + + "github.com/filecoin-project/venus/app/submodule/chain" + "github.com/filecoin-project/venus/app/submodule/network" + "github.com/filecoin-project/venus/pkg/repo" + "github.com/filecoin-project/venus/pkg/vf3" + v1api "github.com/filecoin-project/venus/venus-shared/api/chain/v1" + "github.com/filecoin-project/venus/venus-shared/api/f3" + logging "github.com/ipfs/go-log" +) + +var log = logging.Logger("f3") + +type F3Submodule struct { + F3 *vf3.F3 +} + +func NewF3Submodule(ctx context.Context, repo repo.Repo, chain *chain.ChainSubmodule, network *network.NetworkSubmodule, walletAPI v1api.IWallet) (*F3Submodule, error) { + netconf := repo.Config().NetworkParams + if !netconf.F3Enabled { + return &F3Submodule{ + F3: &vf3.F3{}, + }, nil + } + m, err := vf3.New(ctx, vf3.F3Params{ + NetworkName: network.NetworkName, + NetworkParams: netconf, + PubSub: network.Pubsub, + Host: network.Host, + ChainStore: chain.ChainReader, + StateManager: chain.Stmgr, + Datastore: repo.ChainDatastore(), + Wallet: walletAPI, + }) + if err != nil { + return nil, err + } + + return &F3Submodule{m}, nil +} + +func (m *F3Submodule) API() f3.F3 { + return &f3API{ + f3module: m, + } +} + +func (m *F3Submodule) V0API() f3.F3 { + return &f3API{ + f3module: m, + } +} diff --git a/app/submodule/network/network_submodule.go b/app/submodule/network/network_submodule.go index b8ee6f3f4b..d36f99b258 100644 --- a/app/submodule/network/network_submodule.go +++ b/app/submodule/network/network_submodule.go @@ -178,7 +178,7 @@ func NewNetworkSubmodule(ctx context.Context, } sk := net.NewScoreKeeper() - gsub, err := net.NewGossipSub(ctx, peerHost, sk, networkName, cfg.NetworkParams.DrandSchedule, bootNodes, cfg.PubsubConfig.Bootstrapper) + gsub, err := net.NewGossipSub(ctx, peerHost, sk, networkName, cfg.NetworkParams.DrandSchedule, bootNodes, cfg.PubsubConfig.Bootstrapper, config.Repo().Config().NetworkParams.F3Enabled) if err != nil { return nil, errors.Wrap(err, "failed to set up network") } diff --git a/fixtures/networks/butterfly.go b/fixtures/networks/butterfly.go index 69935740d7..111268fb35 100644 --- a/fixtures/networks/butterfly.go +++ b/fixtures/networks/butterfly.go @@ -69,6 +69,8 @@ func ButterflySnapNet() *NetworkConf { AllowableClockDriftSecs: 1, Eip155ChainID: 3141592, ActorDebugging: false, + F3Enabled: true, + F3BootstrapEpoch: 200, }, } diff --git a/fixtures/networks/calibration.go b/fixtures/networks/calibration.go index 7ea665cd87..9410b0e35a 100644 --- a/fixtures/networks/calibration.go +++ b/fixtures/networks/calibration.go @@ -75,6 +75,8 @@ func Calibration() *NetworkConf { AllowableClockDriftSecs: 1, Eip155ChainID: 314159, ActorDebugging: false, + F3Enabled: false, + F3BootstrapEpoch: -1, }, } diff --git a/fixtures/networks/forcenet.go b/fixtures/networks/forcenet.go index 43b3f756e4..de3cf0eb9d 100644 --- a/fixtures/networks/forcenet.go +++ b/fixtures/networks/forcenet.go @@ -71,6 +71,8 @@ func ForceNet() *NetworkConf { AllowableClockDriftSecs: 1, Eip155ChainID: 31415926, ActorDebugging: true, + F3Enabled: true, + F3BootstrapEpoch: 100, }, } nc.Network.DrandSchedule[nc.Network.ForkUpgradeParam.UpgradePhoenixHeight] = config.DrandQuicknet diff --git a/fixtures/networks/interopnet.go b/fixtures/networks/interopnet.go index 8ef7f77dc9..e0f422a697 100644 --- a/fixtures/networks/interopnet.go +++ b/fixtures/networks/interopnet.go @@ -69,6 +69,8 @@ func InteropNet() *NetworkConf { AllowableClockDriftSecs: 1, Eip155ChainID: 3141592, ActorDebugging: false, + F3Enabled: true, + F3BootstrapEpoch: 1000, }, } diff --git a/fixtures/networks/mainnet.go b/fixtures/networks/mainnet.go index d33b17e679..c3a71852a9 100644 --- a/fixtures/networks/mainnet.go +++ b/fixtures/networks/mainnet.go @@ -74,6 +74,8 @@ func Mainnet() *NetworkConf { AllowableClockDriftSecs: 1, Eip155ChainID: 314, ActorDebugging: false, + F3Enabled: false, + F3BootstrapEpoch: -1, }, } diff --git a/fixtures/networks/net_2k.go b/fixtures/networks/net_2k.go index ee2c474452..ea70dd92b4 100644 --- a/fixtures/networks/net_2k.go +++ b/fixtures/networks/net_2k.go @@ -65,6 +65,8 @@ func Net2k() *NetworkConf { AllowableClockDriftSecs: 1, Eip155ChainID: 31415926, ActorDebugging: true, + F3Enabled: true, + F3BootstrapEpoch: 100, }, } diff --git a/go.mod b/go.mod index 289bc4912b..4428447975 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/dgraph-io/badger/v2 v2.2007.4 github.com/docker/go-units v0.5.0 github.com/drand/drand v1.5.11 - github.com/drand/kyber v1.3.0 + github.com/drand/kyber v1.3.1 github.com/dustin/go-humanize v1.0.1 github.com/etherlabsio/healthcheck/v2 v2.0.0 github.com/fatih/color v1.15.0 @@ -27,6 +27,7 @@ require ( github.com/filecoin-project/go-commp-utils v0.1.3 github.com/filecoin-project/go-crypto v0.0.1 github.com/filecoin-project/go-data-transfer/v2 v2.0.0-rc6 + github.com/filecoin-project/go-f3 v0.0.2 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-markets v1.28.2 github.com/filecoin-project/go-jsonrpc v0.1.5 @@ -75,7 +76,7 @@ require ( github.com/ipld/go-car v0.6.2 github.com/ipld/go-car/v2 v2.13.1 github.com/jbenet/goprocess v0.1.4 - github.com/libp2p/go-libp2p v0.34.1 + github.com/libp2p/go-libp2p v0.35.0 github.com/libp2p/go-libp2p-kad-dht v0.25.2 github.com/libp2p/go-libp2p-pubsub v0.11.0 github.com/libp2p/go-msgio v0.3.0 @@ -114,6 +115,7 @@ require ( ) require ( + github.com/Kubuxu/go-broadcast v0.0.0-20240621161059-1a8c90734cd6 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/ipfs/go-blockservice v0.5.2 // indirect github.com/ipfs/go-ipfs-blockstore v1.3.1 // indirect @@ -160,7 +162,7 @@ require ( github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/crackcomm/go-gitignore v0.0.0-20231225121904-e25f5bc08668 // indirect github.com/cskr/pubsub v1.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -315,7 +317,7 @@ require ( github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect github.com/x448/float16 v0.8.4 // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect go.opentelemetry.io/otel v1.26.0 go.opentelemetry.io/otel/metric v1.26.0 // indirect go.opentelemetry.io/otel/sdk/metric v0.39.0 // indirect diff --git a/go.sum b/go.sum index 5882491bfb..27bda7ea71 100644 --- a/go.sum +++ b/go.sum @@ -75,6 +75,8 @@ github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee h1:8doiS7ib3zi6/K172oDhSKU0dJ/miJramo9NITOMyZQ= github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee/go.mod h1:W0GbEAA4uFNYOGG2cJpmFJ04E6SD1NLELPYZB57/7AY= +github.com/Kubuxu/go-broadcast v0.0.0-20240621161059-1a8c90734cd6 h1:yh2/1fz3ajTaeKskSWxtSBNScdRZfQ/A5nyd9+64T6M= +github.com/Kubuxu/go-broadcast v0.0.0-20240621161059-1a8c90734cd6/go.mod h1:5LOj/fF3Oc/cvJqzDiyfx4XwtBPRWUYEz+V+b13sH5U= github.com/Kubuxu/go-os-helper v0.0.1 h1:EJiD2VUQyh5A9hWJLmc6iWg6yIcJ7jpBcwC8GMGXfDk= github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= @@ -171,8 +173,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= github.com/crackcomm/go-gitignore v0.0.0-20231225121904-e25f5bc08668 h1:ZFUue+PNxmHlu7pYv+IYMtqlaO/0VwaGEqKepZf9JpA= github.com/crackcomm/go-gitignore v0.0.0-20231225121904-e25f5bc08668/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= @@ -215,8 +217,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/drand/drand v1.5.11 h1:7sskUTCsX2lgFiWdGvPh3/P0ZDQKi1lCtI7RQKK010k= github.com/drand/drand v1.5.11/go.mod h1:TvJjCJ/s4Usn4pKRpDC0N1QaCwSt3YC8fRqhZdpOUU0= -github.com/drand/kyber v1.3.0 h1:TVd7+xoRgKQ4Ck1viNLPFy6IWhuZM36Bq6zDXD8Asls= -github.com/drand/kyber v1.3.0/go.mod h1:f+mNHjiGT++CuueBrpeMhFNdKZAsy0tu03bKq9D5LPA= +github.com/drand/kyber v1.3.1 h1:E0p6M3II+loMVwTlAp5zu4+GGZFNiRfq02qZxzw2T+Y= +github.com/drand/kyber v1.3.1/go.mod h1:f+mNHjiGT++CuueBrpeMhFNdKZAsy0tu03bKq9D5LPA= github.com/drand/kyber-bls12381 v0.3.1 h1:KWb8l/zYTP5yrvKTgvhOrk2eNPscbMiUOIeWBnmUxGo= github.com/drand/kyber-bls12381 v0.3.1/go.mod h1:H4y9bLPu7KZA/1efDg+jtJ7emKx+ro3PU7/jWUVt140= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -275,6 +277,8 @@ github.com/filecoin-project/go-data-transfer/v2 v2.0.0-rc6 h1:EsbXTWsBKT764qtX4M github.com/filecoin-project/go-data-transfer/v2 v2.0.0-rc6/go.mod h1:cX1acvFVWC5EXnnmFPWEFXbO7nLUdSZa+nqgi1QpTpw= github.com/filecoin-project/go-ds-versioning v0.1.2 h1:to4pTadv3IeV1wvgbCbN6Vqd+fu+7tveXgv/rCEZy6w= github.com/filecoin-project/go-ds-versioning v0.1.2/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= +github.com/filecoin-project/go-f3 v0.0.2 h1:bzw/GndxntJnUYA+WCaXwHE2qwGRwrFVo9umz3unTUs= +github.com/filecoin-project/go-f3 v0.0.2/go.mod h1:Wry0mNa8z767TBHb7N0cVb+9j00KsHbD2pzsC3li4R8= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88OqLYEo6roi+GiIeOh8= github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= @@ -860,8 +864,8 @@ github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFG github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= github.com/libp2p/go-libp2p v0.1.0/go.mod h1:6D/2OBauqLUoqcADOJpn9WbKqvaM07tDw68qHM0BxUM= github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8= -github.com/libp2p/go-libp2p v0.34.1 h1:fxn9vyLo7vJcXQRNvdRbyPjbzuQgi2UiqC8hEbn8a18= -github.com/libp2p/go-libp2p v0.34.1/go.mod h1:snyJQix4ET6Tj+LeI0VPjjxTtdWpeOhYt5lEY0KirkQ= +github.com/libp2p/go-libp2p v0.35.0 h1:1xS1Bkr9X7GtdvV6ntLnDV9xB1kNjHK1lZ0eaO6gnhc= +github.com/libp2p/go-libp2p v0.35.0/go.mod h1:snyJQix4ET6Tj+LeI0VPjjxTtdWpeOhYt5lEY0KirkQ= github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8= @@ -1398,8 +1402,8 @@ github.com/xorcare/golden v0.6.0/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/ github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 h1:oWgZJmC1DorFZDpfMfWg7xk29yEOZiXmo/wZl+utTI8= github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/U6FtvQ= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw= +github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/pkg/config/config.go b/pkg/config/config.go index ba04bd7e92..00abdca722 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -305,7 +305,9 @@ type NetworkParamsConfig struct { // As per https://github.com/ethereum-lists/chains Eip155ChainID int `json:"-"` // NOTE: DO NOT change this unless you REALLY know what you're doing. This is consensus critical. - ActorDebugging bool `json:"-"` + ActorDebugging bool `json:"-"` + F3Enabled bool `json:"f3Enabled"` + F3BootstrapEpoch abi.ChainEpoch `json:"f3BootstrapEpoch"` } // ForkUpgradeConfig record upgrade parameters diff --git a/pkg/constants/chain_parameters.go b/pkg/constants/chain_parameters.go index be4d408ae5..4268fc9e8a 100644 --- a/pkg/constants/chain_parameters.go +++ b/pkg/constants/chain_parameters.go @@ -1,9 +1,10 @@ package constants import ( + "math" + "github.com/filecoin-project/go-state-types/abi" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" - "math" ) const ( diff --git a/pkg/net/gossipsub.go b/pkg/net/gossipsub.go index 903e22df70..fcd987bffc 100644 --- a/pkg/net/gossipsub.go +++ b/pkg/net/gossipsub.go @@ -13,6 +13,7 @@ import ( "github.com/libp2p/go-libp2p/core/peer" blake2b "github.com/minio/blake2b-simd" + "github.com/filecoin-project/go-f3/gpbft" "github.com/filecoin-project/venus/pkg/config" "github.com/filecoin-project/venus/venus-shared/types" ) @@ -48,6 +49,7 @@ func NewGossipSub(ctx context.Context, drandSchedule map[abi.ChainEpoch]config.DrandEnum, bootNodes []peer.AddrInfo, bs bool, + f3enabled bool, ) (*pubsub.PubSub, error) { bootstrappers := make(map[peer.ID]struct{}) for _, info := range bootNodes { @@ -310,6 +312,9 @@ func NewGossipSub(ctx context.Context, indexerIngestTopic, } allowTopics = append(allowTopics, drandTopics...) + if f3enabled { + allowTopics = append(allowTopics, gpbft.NetworkName(networkName).PubSubTopic()) + } options = append(options, pubsub.WithSubscriptionFilter( pubsub.WrapLimitSubscriptionFilter( diff --git a/pkg/vf3/ec.go b/pkg/vf3/ec.go new file mode 100644 index 0000000000..a90848a907 --- /dev/null +++ b/pkg/vf3/ec.go @@ -0,0 +1,217 @@ +package vf3 + +import ( + "context" + "sort" + "time" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-f3" + "github.com/filecoin-project/go-f3/gpbft" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/venus/pkg/chain" + "github.com/filecoin-project/venus/pkg/statemanger" + "github.com/filecoin-project/venus/pkg/vm" + "github.com/filecoin-project/venus/venus-shared/actors/builtin/miner" + "github.com/filecoin-project/venus/venus-shared/actors/builtin/power" + "github.com/filecoin-project/venus/venus-shared/types" + "golang.org/x/xerrors" +) + +type ecWrapper struct { + ChainStore *chain.Store + StateManager *statemanger.Stmgr + Manifest f3.Manifest +} + +type f3TipSet types.TipSet + +func (ts *f3TipSet) cast() *types.TipSet { + return (*types.TipSet)(ts) +} + +func (ts *f3TipSet) Key() gpbft.TipSetKey { + return ts.cast().Key().Bytes() +} + +func (ts *f3TipSet) Beacon() []byte { + entries := ts.cast().Blocks()[0].BeaconEntries + if len(entries) == 0 { + // Set beacon to a non-nil slice to force the message builder to generate a + // ticket. Otherwise, messages that require ticket, i.e. CONVERGE will fail + // validation due to the absence of ticket. This is a convoluted way of doing it. + // TODO: Rework the F3 message builder APIs to include ticket when needed instead + // of relying on the nil check of beacon. + return []byte{} + } + return entries[len(entries)-1].Data +} + +func (ts *f3TipSet) Epoch() int64 { + return int64(ts.cast().Height()) +} + +func (ts *f3TipSet) Timestamp() time.Time { + return time.Unix(int64(ts.cast().Blocks()[0].Timestamp), 0) +} + +func wrapTS(ts *types.TipSet) f3.TipSet { + if ts == nil { + return nil + } + return (*f3TipSet)(ts) +} + +// GetTipsetByEpoch should return a tipset before the one requested if the requested +// tipset does not exist due to null epochs +func (ec *ecWrapper) GetTipsetByEpoch(ctx context.Context, epoch int64) (f3.TipSet, error) { + ts, err := ec.ChainStore.GetTipSetByHeight(ctx, nil, abi.ChainEpoch(epoch), true) + if err != nil { + return nil, xerrors.Errorf("getting tipset by height: %w", err) + } + return wrapTS(ts), nil +} + +func (ec *ecWrapper) GetTipset(ctx context.Context, tsk gpbft.TipSetKey) (f3.TipSet, error) { + tskLotus, err := types.TipSetKeyFromBytes(tsk) + if err != nil { + return nil, xerrors.Errorf("decoding tsk: %w", err) + } + + ts, err := ec.ChainStore.GetTipSet(ctx, tskLotus) + if err != nil { + return nil, xerrors.Errorf("getting tipset by key: %w", err) + } + + return wrapTS(ts), nil +} + +func (ec *ecWrapper) GetHead(_ context.Context) (f3.TipSet, error) { + return wrapTS(ec.ChainStore.GetHead()), nil +} + +func (ec *ecWrapper) GetParent(ctx context.Context, tsF3 f3.TipSet) (f3.TipSet, error) { + var ts *types.TipSet + if tsW, ok := tsF3.(*f3TipSet); ok { + ts = tsW.cast() + } else { + // There are only two implementations of F3.TipSet: f3TipSet, and one in fake EC + // backend. + // + // TODO: Revisit the type check here and remove as needed once testing + // is over and fake EC backend goes away. + tskLotus, err := types.TipSetKeyFromBytes(tsF3.Key()) + if err != nil { + return nil, xerrors.Errorf("decoding tsk: %w", err) + } + ts, err = ec.ChainStore.GetTipSet(ctx, tskLotus) + if err != nil { + return nil, xerrors.Errorf("getting tipset by key for get parent: %w", err) + } + } + parentTS, err := ec.ChainStore.GetTipSet(ctx, ts.Parents()) + if err != nil { + return nil, xerrors.Errorf("getting parent tipset: %w", err) + } + return wrapTS(parentTS), nil +} + +func (ec *ecWrapper) GetPowerTable(ctx context.Context, tskF3 gpbft.TipSetKey) (gpbft.PowerEntries, error) { + tskLotus, err := types.TipSetKeyFromBytes(tskF3) + if err != nil { + return nil, xerrors.Errorf("decoding tsk: %w", err) + } + ts, err := ec.ChainStore.GetTipSet(ctx, tskLotus) + if err != nil { + return nil, xerrors.Errorf("getting tipset by key for get parent: %w", err) + } + + _, state, err := ec.StateManager.ParentState(ctx, ts) + if err != nil { + return nil, xerrors.Errorf("loading the state tree: %w", err) + } + powerAct, found, err := state.GetActor(ctx, power.Address) + if err != nil { + return nil, xerrors.Errorf("getting the power actor: %w", err) + } + if !found { + return nil, xerrors.Errorf("not found the power actor by address: %s", power.Address) + } + + powerState, err := power.Load(ec.ChainStore.Store(ctx), powerAct) + if err != nil { + return nil, xerrors.Errorf("loading power actor state: %w", err) + } + + var powerEntries gpbft.PowerEntries + err = powerState.ForEachClaim(func(minerAddr address.Address, claim power.Claim) error { + if claim.QualityAdjPower.Sign() <= 0 { + return nil + } + + // TODO: optimize + ok, err := powerState.MinerNominalPowerMeetsConsensusMinimum(minerAddr) + if err != nil { + return xerrors.Errorf("checking consensus minimums: %w", err) + } + if !ok { + return nil + } + + id, err := address.IDFromAddress(minerAddr) + if err != nil { + return xerrors.Errorf("transforming address to ID: %w", err) + } + + pe := gpbft.PowerEntry{ + ID: gpbft.ActorID(id), + Power: claim.QualityAdjPower.Int, + } + + act, found, err := state.GetActor(ctx, minerAddr) + if err != nil { + return xerrors.Errorf("(get sset) failed to load miner actor: %w", err) + } + if !found { + return xerrors.Errorf("(get sset) failed to find miner actor by address: %s", minerAddr) + } + mstate, err := miner.Load(ec.ChainStore.Store(ctx), act) + if err != nil { + return xerrors.Errorf("(get sset) failed to load miner actor state: %w", err) + } + + info, err := mstate.Info() + if err != nil { + return xerrors.Errorf("failed to load actor info: %w", err) + } + // check fee debt + if debt, err := mstate.FeeDebt(); err != nil { + return err + } else if !debt.IsZero() { + // fee debt don't add the miner to power table + return nil + } + // check consensus faults + if ts.Height() <= info.ConsensusFaultElapsed { + return nil + } + + waddr, err := vm.ResolveToDeterministicAddress(ctx, state, info.Worker, ec.ChainStore.Store(ctx)) + if err != nil { + return xerrors.Errorf("resolve miner worker address: %w", err) + } + + if waddr.Protocol() != address.BLS { + return xerrors.Errorf("wrong type of worker address") + } + pe.PubKey = gpbft.PubKey(waddr.Payload()) + powerEntries = append(powerEntries, pe) + return nil + }) + if err != nil { + return nil, xerrors.Errorf("collecting the power table: %w", err) + } + + sort.Sort(powerEntries) + return powerEntries, nil +} diff --git a/pkg/vf3/f3.go b/pkg/vf3/f3.go new file mode 100644 index 0000000000..3ceb28c35e --- /dev/null +++ b/pkg/vf3/f3.go @@ -0,0 +1,150 @@ +package vf3 + +import ( + "context" + "errors" + "time" + + "github.com/ipfs/go-datastore" + "github.com/ipfs/go-datastore/namespace" + pubsub "github.com/libp2p/go-libp2p-pubsub" + "github.com/libp2p/go-libp2p/core/host" + "golang.org/x/xerrors" + + "github.com/filecoin-project/go-f3" + "github.com/filecoin-project/go-f3/blssig" + "github.com/filecoin-project/go-f3/certs" + "github.com/filecoin-project/go-f3/gpbft" + "github.com/filecoin-project/venus/pkg/chain" + "github.com/filecoin-project/venus/pkg/config" + "github.com/filecoin-project/venus/pkg/constants" + "github.com/filecoin-project/venus/pkg/statemanger" + v1api "github.com/filecoin-project/venus/venus-shared/api/chain/v1" + logging "github.com/ipfs/go-log" +) + +type F3 struct { + inner *f3.F3 + + signer gpbft.Signer +} + +type F3Params struct { + NetworkName string + NetworkParams *config.NetworkParamsConfig + PubSub *pubsub.PubSub + Host host.Host + ChainStore *chain.Store + StateManager *statemanger.Stmgr + Datastore datastore.Batching + Wallet v1api.IWallet +} + +var log = logging.Logger("f3") + +func New(mctx context.Context, params F3Params) (*F3, error) { + manifest := f3.LocalnetManifest() + manifest.NetworkName = gpbft.NetworkName(params.NetworkName) + manifest.ECDelay = 2 * time.Duration(params.NetworkParams.BlockDelay) * time.Second + manifest.ECPeriod = manifest.ECDelay + manifest.BootstrapEpoch = int64(params.NetworkParams.F3BootstrapEpoch) + manifest.ECFinality = int64(constants.Finality) + + ds := namespace.Wrap(params.Datastore, datastore.NewKey("/f3")) + ec := &ecWrapper{ + ChainStore: params.ChainStore, + StateManager: params.StateManager, + Manifest: manifest, + } + verif := blssig.VerifierWithKeyOnG1() + + module, err := f3.New(mctx, manifest, ds, + params.Host, params.PubSub, verif, ec, log, nil) + + if err != nil { + return nil, xerrors.Errorf("creating F3: %w", err) + } + + fff := &F3{ + inner: module, + signer: &signer{params.Wallet}, + } + + go func() { + err := fff.inner.Run(mctx) + if err != nil { + log.Errorf("running f3: %+v", err) + } + }() + + return fff, nil +} + +// Participate runs the participation loop for givine minerID +// It is blocking +func (fff *F3) Participate(ctx context.Context, minerIDAddress uint64, errCh chan<- string) { + defer close(errCh) + + for ctx.Err() == nil { + + // create channel for some buffer so we don't get dropped under high load + msgCh := make(chan *gpbft.MessageBuilder, 4) + // SubscribeForMessagesToSign will close the channel if it fills up + // so using the closer is not necessary, we can just drop it on the floor + _ = fff.inner.SubscribeForMessagesToSign(msgCh) + + participateOnce := func(mb *gpbft.MessageBuilder) error { + signatureBuilder, err := mb.PrepareSigningInputs(gpbft.ActorID(minerIDAddress)) + if errors.Is(err, gpbft.ErrNoPower) { + // we don't have any power in F3, continue + log.Debug("no power to participate in F3: %+v", err) + return nil + } + if err != nil { + log.Errorf("preparing signing inputs: %+v", err) + return err + } + // if worker keys were stored not in the node, the signatureBuilder can be send there + // the sign can be called where the keys are stored and then + // {signatureBuilder, payloadSig, vrfSig} can be sent back to lotus for broadcast + payloadSig, vrfSig, err := signatureBuilder.Sign(fff.signer) + if err != nil { + log.Errorf("signing message: %+v", err) + return err + } + log.Infof("miner with id %d is sending message in F3", minerIDAddress) + fff.inner.Broadcast(ctx, signatureBuilder, payloadSig, vrfSig) + return nil + } + + inner: + for ctx.Err() == nil { + select { + case mb, ok := <-msgCh: + if !ok { + // the broadcast bus kicked us out + log.Warnf("lost message bus subscription, retrying") + break inner + } + + err := participateOnce(mb) + if err != nil { + errCh <- err.Error() + } else { + errCh <- "" + } + + case <-ctx.Done(): + return + } + } + } +} + +func (fff *F3) GetCert(ctx context.Context, instance uint64) (*certs.FinalityCertificate, error) { + return fff.inner.GetCert(ctx, instance) +} + +func (fff *F3) GetLatestCert(ctx context.Context) (*certs.FinalityCertificate, error) { + return fff.inner.GetLatestCert(ctx) +} diff --git a/pkg/vf3/signer.go b/pkg/vf3/signer.go new file mode 100644 index 0000000000..eabd80fe7e --- /dev/null +++ b/pkg/vf3/signer.go @@ -0,0 +1,37 @@ +package vf3 + +import ( + "context" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-f3/gpbft" + v1api "github.com/filecoin-project/venus/venus-shared/api/chain/v1" + "github.com/filecoin-project/venus/venus-shared/types" + "golang.org/x/xerrors" +) + +type signer struct { + wallet v1api.IWallet +} + +// Sign signs a message with the private key corresponding to a public key. +// The the key must be known by the wallet and be of BLS type. +func (s *signer) Sign(sender gpbft.PubKey, msg []byte) ([]byte, error) { + addr, err := address.NewBLSAddress(sender) + if err != nil { + return nil, xerrors.Errorf("converting pubkey to address: %w", err) + } + sig, err := s.wallet.WalletSign(context.TODO(), addr, msg, types.MsgMeta{Type: types.MTUnknown}) + if err != nil { + return nil, xerrors.Errorf("error while signing: %w", err) + } + return sig.Data, nil +} + +// MarshalPayloadForSigning marshals the given payload into the bytes that should be signed. +// This should usually call `Payload.MarshalForSigning(NetworkName)` except when testing as +// that method is slow (computes a merkle tree that's necessary for testing). +// Implementations must be safe for concurrent use. +func (s *signer) MarshalPayloadForSigning(nn gpbft.NetworkName, p *gpbft.Payload) []byte { + return p.MarshalForSigning(nn) +} diff --git a/venus-devtool/api-gen/common/common.go b/venus-devtool/api-gen/common/common.go index b4e1102c9e..6c6984ab8f 100644 --- a/venus-devtool/api-gen/common/common.go +++ b/venus-devtool/api-gen/common/common.go @@ -9,6 +9,7 @@ import ( "reflect" "github.com/filecoin-project/venus/venus-devtool/util" + "github.com/filecoin-project/venus/venus-shared/api/f3" gatewayv0 "github.com/filecoin-project/venus/venus-shared/api/gateway/v0" gatewayv1 "github.com/filecoin-project/venus/venus-shared/api/gateway/v1" gatewayv2 "github.com/filecoin-project/venus/venus-shared/api/gateway/v2" @@ -112,6 +113,17 @@ func init() { MethodNamespace: "VENUS_MARKET_CLIENT", }, }, + util.APIMeta{ + Type: reflect.TypeOf((*f3.F3)(nil)).Elem(), + ParseOpt: util.InterfaceParseOption{ + ImportPath: "github.com/filecoin-project/venus/venus-shared/api/f3", + IncludeAll: true, + }, + RPCMeta: util.RPCMeta{ + Version: 0, + MethodNamespace: "F3", + }, + }, ) } diff --git a/venus-devtool/api-gen/example.go b/venus-devtool/api-gen/example.go index bbbcf5fc15..030968bac6 100644 --- a/venus-devtool/api-gen/example.go +++ b/venus-devtool/api-gen/example.go @@ -35,6 +35,7 @@ import ( "github.com/libp2p/go-libp2p/core/protocol" "github.com/multiformats/go-multiaddr" + "github.com/filecoin-project/go-f3/certs" "github.com/filecoin-project/venus/pkg/constants" "github.com/filecoin-project/venus/venus-shared/api/chain" "github.com/filecoin-project/venus/venus-shared/types" @@ -327,6 +328,7 @@ func init() { addExample(retrievalmarket.CborGenCompatibleNode{}) addExample(gateway.HostNode) + addExample(&certs.FinalityCertificate{}) } func ExampleValue(method string, t, parent reflect.Type) interface{} { diff --git a/venus-shared/api/f3/api.go b/venus-shared/api/f3/api.go new file mode 100644 index 0000000000..9fd60f8998 --- /dev/null +++ b/venus-shared/api/f3/api.go @@ -0,0 +1,22 @@ +package f3 + +import ( + "context" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-f3/certs" +) + +type F3 interface { + // F3Participate should be called by a miner node to participate in signing F3 consensus. + // The address should be of type ID + // The returned channel will never be closed by the F3 + // If it is closed without the context being cancelled, the caller should retry. + // The values returned on the channel will inform the caller about participation + // Empty strings will be sent if participation succeeded, non-empty strings explain possible errors. + F3Participate(ctx context.Context, minerID address.Address) (<-chan string, error) //perm:admin + // F3GetCertificate returns a finality certificate at given instance number + F3GetCertificate(ctx context.Context, instance uint64) (*certs.FinalityCertificate, error) //perm:read + // F3GetLatestCertificate returns the latest finality certificate + F3GetLatestCertificate(ctx context.Context) (*certs.FinalityCertificate, error) //perm:read +} diff --git a/venus-shared/api/f3/client_gen.go b/venus-shared/api/f3/client_gen.go new file mode 100644 index 0000000000..acbad0a4d4 --- /dev/null +++ b/venus-shared/api/f3/client_gen.go @@ -0,0 +1,54 @@ +// Code generated by github.com/filecoin-project/venus/venus-devtool/api-gen. DO NOT EDIT. +package f3 + +import ( + "context" + "fmt" + "net/http" + + "github.com/filecoin-project/go-jsonrpc" + + "github.com/filecoin-project/venus/venus-shared/api" +) + +const MajorVersion = 0 +const APINamespace = "f3.F3" +const MethodNamespace = "F3" + +// NewF3RPC creates a new httpparse jsonrpc remotecli. +func NewF3RPC(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (F3, jsonrpc.ClientCloser, error) { + endpoint, err := api.Endpoint(addr, MajorVersion) + if err != nil { + return nil, nil, fmt.Errorf("invalid addr %s: %w", addr, err) + } + + if requestHeader == nil { + requestHeader = http.Header{} + } + requestHeader.Set(api.VenusAPINamespaceHeader, APINamespace) + + var res F3Struct + closer, err := jsonrpc.NewMergeClient(ctx, endpoint, MethodNamespace, api.GetInternalStructs(&res), requestHeader, opts...) + + return &res, closer, err +} + +// DialF3RPC is a more convinient way of building client, as it resolves any format (url, multiaddr) of addr string. +func DialF3RPC(ctx context.Context, addr string, token string, requestHeader http.Header, opts ...jsonrpc.Option) (F3, jsonrpc.ClientCloser, error) { + ainfo := api.NewAPIInfo(addr, token) + endpoint, err := ainfo.DialArgs(api.VerString(MajorVersion)) + if err != nil { + return nil, nil, fmt.Errorf("get dial args: %w", err) + } + + if requestHeader == nil { + requestHeader = http.Header{} + } + requestHeader.Set(api.VenusAPINamespaceHeader, APINamespace) + ainfo.SetAuthHeader(requestHeader) + + var res F3Struct + closer, err := jsonrpc.NewMergeClient(ctx, endpoint, MethodNamespace, api.GetInternalStructs(&res), requestHeader, opts...) + + return &res, closer, err +} diff --git a/venus-shared/api/f3/method.md b/venus-shared/api/f3/method.md new file mode 100644 index 0000000000..b559084bb7 --- /dev/null +++ b/venus-shared/api/f3/method.md @@ -0,0 +1,156 @@ +# Sample code of curl + +```bash +# corresponding to the value of Inputs Tag of each API +curl http://:/rpc/v0 -X POST -H "Content-Type: application/json" -H "Authorization: Bearer " -d '{"method": "F3.", "params": , "id": 0}' +``` +# Groups + +* [F3](#f3) + * [F3GetCertificate](#f3getcertificate) + * [F3GetLatestCertificate](#f3getlatestcertificate) + * [F3Participate](#f3participate) + +## F3 + +### F3GetCertificate +F3GetCertificate returns a finality certificate at given instance number + + +Perms: read + +Inputs: +```json +[ + 42 +] +``` + +Response: +```json +{ + "GPBFTInstance": 0, + "ECChain": null, + "SupplementalData": { + "Commitments": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "PowerTable": null + }, + "Signers": [ + 0 + ], + "Signature": null, + "PowerTableDelta": null +} +``` + +### F3GetLatestCertificate +F3GetLatestCertificate returns the latest finality certificate + + +Perms: read + +Inputs: `[]` + +Response: +```json +{ + "GPBFTInstance": 0, + "ECChain": null, + "SupplementalData": { + "Commitments": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "PowerTable": null + }, + "Signers": [ + 0 + ], + "Signature": null, + "PowerTableDelta": null +} +``` + +### F3Participate +F3Participate should be called by a miner node to participate in signing F3 consensus. +The address should be of type ID +The returned channel will never be closed by the F3 +If it is closed without the context being cancelled, the caller should retry. +The values returned on the channel will inform the caller about participation +Empty strings will be sent if participation succeeded, non-empty strings explain possible errors. + + +Perms: admin + +Inputs: +```json +[ + "f01234" +] +``` + +Response: `"string value"` + diff --git a/venus-shared/api/f3/mock/mock_f3.go b/venus-shared/api/f3/mock/mock_f3.go new file mode 100644 index 0000000000..5edda7eea6 --- /dev/null +++ b/venus-shared/api/f3/mock/mock_f3.go @@ -0,0 +1,82 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/filecoin-project/venus/venus-shared/api/f3 (interfaces: F3) + +// Package mock is a generated GoMock package. +package mock + +import ( + context "context" + reflect "reflect" + + address "github.com/filecoin-project/go-address" + certs "github.com/filecoin-project/go-f3/certs" + gomock "github.com/golang/mock/gomock" +) + +// MockF3 is a mock of F3 interface. +type MockF3 struct { + ctrl *gomock.Controller + recorder *MockF3MockRecorder +} + +// MockF3MockRecorder is the mock recorder for MockF3. +type MockF3MockRecorder struct { + mock *MockF3 +} + +// NewMockF3 creates a new mock instance. +func NewMockF3(ctrl *gomock.Controller) *MockF3 { + mock := &MockF3{ctrl: ctrl} + mock.recorder = &MockF3MockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockF3) EXPECT() *MockF3MockRecorder { + return m.recorder +} + +// F3GetCertificate mocks base method. +func (m *MockF3) F3GetCertificate(arg0 context.Context, arg1 uint64) (*certs.FinalityCertificate, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "F3GetCertificate", arg0, arg1) + ret0, _ := ret[0].(*certs.FinalityCertificate) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// F3GetCertificate indicates an expected call of F3GetCertificate. +func (mr *MockF3MockRecorder) F3GetCertificate(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "F3GetCertificate", reflect.TypeOf((*MockF3)(nil).F3GetCertificate), arg0, arg1) +} + +// F3GetLatestCertificate mocks base method. +func (m *MockF3) F3GetLatestCertificate(arg0 context.Context) (*certs.FinalityCertificate, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "F3GetLatestCertificate", arg0) + ret0, _ := ret[0].(*certs.FinalityCertificate) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// F3GetLatestCertificate indicates an expected call of F3GetLatestCertificate. +func (mr *MockF3MockRecorder) F3GetLatestCertificate(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "F3GetLatestCertificate", reflect.TypeOf((*MockF3)(nil).F3GetLatestCertificate), arg0) +} + +// F3Participate mocks base method. +func (m *MockF3) F3Participate(arg0 context.Context, arg1 address.Address) (<-chan string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "F3Participate", arg0, arg1) + ret0, _ := ret[0].(<-chan string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// F3Participate indicates an expected call of F3Participate. +func (mr *MockF3MockRecorder) F3Participate(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "F3Participate", reflect.TypeOf((*MockF3)(nil).F3Participate), arg0, arg1) +} diff --git a/venus-shared/api/f3/proxy_gen.go b/venus-shared/api/f3/proxy_gen.go new file mode 100644 index 0000000000..1932c96239 --- /dev/null +++ b/venus-shared/api/f3/proxy_gen.go @@ -0,0 +1,27 @@ +// Code generated by github.com/filecoin-project/venus/venus-devtool/api-gen. DO NOT EDIT. +package f3 + +import ( + "context" + + address "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-f3/certs" +) + +type F3Struct struct { + Internal struct { + F3GetCertificate func(ctx context.Context, instance uint64) (*certs.FinalityCertificate, error) `perm:"read"` + F3GetLatestCertificate func(ctx context.Context) (*certs.FinalityCertificate, error) `perm:"read"` + F3Participate func(ctx context.Context, minerID address.Address) (<-chan string, error) `perm:"admin"` + } +} + +func (s *F3Struct) F3GetCertificate(p0 context.Context, p1 uint64) (*certs.FinalityCertificate, error) { + return s.Internal.F3GetCertificate(p0, p1) +} +func (s *F3Struct) F3GetLatestCertificate(p0 context.Context) (*certs.FinalityCertificate, error) { + return s.Internal.F3GetLatestCertificate(p0) +} +func (s *F3Struct) F3Participate(p0 context.Context, p1 address.Address) (<-chan string, error) { + return s.Internal.F3Participate(p0, p1) +}