sector commitments make it all the way to the chain
This commit is contained in:
parent
b7c6333fef
commit
5c32725510
@ -84,6 +84,7 @@ type FullNode interface {
|
|||||||
ChainWaitMsg(context.Context, cid.Cid) (*MsgWait, error)
|
ChainWaitMsg(context.Context, cid.Cid) (*MsgWait, error)
|
||||||
ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error)
|
ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error)
|
||||||
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
|
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
|
||||||
|
ChainGetBlockReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error)
|
||||||
|
|
||||||
// if tipset is nil, we'll use heaviest
|
// if tipset is nil, we'll use heaviest
|
||||||
ChainCall(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error)
|
ChainCall(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error)
|
||||||
|
@ -46,6 +46,7 @@ type FullNodeStruct struct {
|
|||||||
ChainWaitMsg func(context.Context, cid.Cid) (*MsgWait, error) `perm:"read"`
|
ChainWaitMsg func(context.Context, cid.Cid) (*MsgWait, error) `perm:"read"`
|
||||||
ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"`
|
ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"`
|
||||||
ChainGetBlockMessages func(context.Context, cid.Cid) (*BlockMessages, error) `perm:"read"`
|
ChainGetBlockMessages func(context.Context, cid.Cid) (*BlockMessages, error) `perm:"read"`
|
||||||
|
ChainGetBlockReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"`
|
||||||
ChainCall func(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"`
|
ChainCall func(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"`
|
||||||
|
|
||||||
MpoolPending func(context.Context, *types.TipSet) ([]*types.SignedMessage, error) `perm:"read"`
|
MpoolPending func(context.Context, *types.TipSet) ([]*types.SignedMessage, error) `perm:"read"`
|
||||||
@ -195,6 +196,10 @@ func (c *FullNodeStruct) ChainGetBlockMessages(ctx context.Context, b cid.Cid) (
|
|||||||
return c.Internal.ChainGetBlockMessages(ctx, b)
|
return c.Internal.ChainGetBlockMessages(ctx, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *FullNodeStruct) ChainGetBlockReceipts(ctx context.Context, b cid.Cid) ([]*types.MessageReceipt, error) {
|
||||||
|
return c.Internal.ChainGetBlockReceipts(ctx, b)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *FullNodeStruct) ChainNotify(ctx context.Context) (<-chan *store.HeadChange, error) {
|
func (c *FullNodeStruct) ChainNotify(ctx context.Context) (<-chan *store.HeadChange, error) {
|
||||||
return c.Internal.ChainNotify(ctx)
|
return c.Internal.ChainNotify(ctx)
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package gen
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
bls "github.com/filecoin-project/go-bls-sigs"
|
bls "github.com/filecoin-project/go-bls-sigs"
|
||||||
cid "github.com/ipfs/go-cid"
|
cid "github.com/ipfs/go-cid"
|
||||||
@ -69,14 +70,20 @@ func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, miner address.A
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "apply message failure")
|
return nil, errors.Wrap(err, "apply message failure")
|
||||||
}
|
}
|
||||||
|
if rec.ActorErr != nil {
|
||||||
|
fmt.Println(rec.ActorErr)
|
||||||
|
}
|
||||||
|
|
||||||
receipts = append(receipts, rec)
|
receipts = append(receipts, rec.MessageReceipt)
|
||||||
}
|
}
|
||||||
for _, msg := range secpkMessages {
|
for _, msg := range secpkMessages {
|
||||||
rec, err := vmi.ApplyMessage(ctx, &msg.Message)
|
rec, err := vmi.ApplyMessage(ctx, &msg.Message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "apply message failure")
|
return nil, errors.Wrap(err, "apply message failure")
|
||||||
}
|
}
|
||||||
|
if rec.ActorErr != nil {
|
||||||
|
fmt.Println(rec.ActorErr)
|
||||||
|
}
|
||||||
|
|
||||||
receipts = append(receipts, rec.MessageReceipt)
|
receipts = append(receipts, rec.MessageReceipt)
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,15 @@ func BigFromBytes(b []byte) BigInt {
|
|||||||
return BigInt{i}
|
return BigInt{i}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BigFromString(s string) (BigInt, error) {
|
||||||
|
v, ok := big.NewInt(0).SetString(s, 10)
|
||||||
|
if !ok {
|
||||||
|
return BigInt{}, fmt.Errorf("failed to parse string as a big int")
|
||||||
|
}
|
||||||
|
|
||||||
|
return BigInt{v}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func BigMul(a, b BigInt) BigInt {
|
func BigMul(a, b BigInt) BigInt {
|
||||||
return BigInt{big.NewInt(0).Mul(a.Int, b.Int)}
|
return BigInt{big.NewInt(0).Mul(a.Int, b.Int)}
|
||||||
}
|
}
|
||||||
|
@ -86,15 +86,22 @@ var chainGetBlock = &cli.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recpts, err := api.ChainGetBlockReceipts(ctx, bcid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
cblock := struct {
|
cblock := struct {
|
||||||
types.BlockHeader
|
types.BlockHeader
|
||||||
BlsMessages []*types.Message
|
BlsMessages []*types.Message
|
||||||
SecpkMessages []*types.SignedMessage
|
SecpkMessages []*types.SignedMessage
|
||||||
|
MessageReceipts []*types.MessageReceipt
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
cblock.BlockHeader = *blk
|
cblock.BlockHeader = *blk
|
||||||
cblock.BlsMessages = msgs.BlsMessages
|
cblock.BlsMessages = msgs.BlsMessages
|
||||||
cblock.SecpkMessages = msgs.SecpkMessages
|
cblock.SecpkMessages = msgs.SecpkMessages
|
||||||
|
cblock.MessageReceipts = recpts
|
||||||
|
|
||||||
out, err := json.MarshalIndent(cblock, "", " ")
|
out, err := json.MarshalIndent(cblock, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -109,4 +109,5 @@ var Commands = []*cli.Command{
|
|||||||
walletCmd,
|
walletCmd,
|
||||||
createMinerCmd,
|
createMinerCmd,
|
||||||
stateCmd,
|
stateCmd,
|
||||||
|
sendCmd,
|
||||||
}
|
}
|
||||||
|
94
cli/send.go
Normal file
94
cli/send.go
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
|
types "github.com/filecoin-project/go-lotus/chain/types"
|
||||||
|
"gopkg.in/urfave/cli.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var sendCmd = &cli.Command{
|
||||||
|
Name: "send",
|
||||||
|
Usage: "send funds between accounts",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "source",
|
||||||
|
Usage: "optinally specifiy the account to send funds from",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
api, err := GetAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
|
if cctx.Args().Len() != 2 {
|
||||||
|
return fmt.Errorf("'send' expects two arguments, target and amount")
|
||||||
|
}
|
||||||
|
|
||||||
|
toAddr, err := address.NewFromString(cctx.Args().Get(0))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
val, err := types.BigFromString(cctx.Args().Get(1))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var fromAddr address.Address
|
||||||
|
if from := cctx.String("source"); from == "" {
|
||||||
|
defaddr, err := api.WalletDefaultAddress(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fromAddr = defaddr
|
||||||
|
} else {
|
||||||
|
addr, err := address.NewFromString(from)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fromAddr = addr
|
||||||
|
}
|
||||||
|
|
||||||
|
nonce, err := api.MpoolGetNonce(ctx, fromAddr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := &types.Message{
|
||||||
|
From: fromAddr,
|
||||||
|
To: toAddr,
|
||||||
|
Value: val,
|
||||||
|
Nonce: nonce,
|
||||||
|
GasLimit: types.NewInt(10000),
|
||||||
|
GasPrice: types.NewInt(1),
|
||||||
|
}
|
||||||
|
|
||||||
|
sermsg, err := msg.Serialize()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sig, err := api.WalletSign(ctx, fromAddr, sermsg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
smsg := &types.SignedMessage{
|
||||||
|
Message: *msg,
|
||||||
|
Signature: *sig,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := api.MpoolPush(ctx, smsg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
8
go.mod
8
go.mod
@ -61,10 +61,10 @@ require (
|
|||||||
github.com/multiformats/go-multiaddr-net v0.0.1
|
github.com/multiformats/go-multiaddr-net v0.0.1
|
||||||
github.com/multiformats/go-multihash v0.0.6
|
github.com/multiformats/go-multihash v0.0.6
|
||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/polydawn/refmt v0.0.0-20190804001829-26ba426d088b
|
github.com/polydawn/refmt v0.0.0-20190731040541-eff0b363297a
|
||||||
github.com/prometheus/common v0.6.0
|
github.com/prometheus/common v0.6.0
|
||||||
github.com/smartystreets/assertions v1.0.1 // indirect
|
github.com/smartystreets/assertions v1.0.1 // indirect
|
||||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect
|
github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945 // indirect
|
||||||
github.com/stretchr/testify v1.3.0
|
github.com/stretchr/testify v1.3.0
|
||||||
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
|
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
|
||||||
github.com/whyrusleeping/pubsub v0.0.0-20131020042734-02de8aa2db3d
|
github.com/whyrusleeping/pubsub v0.0.0-20131020042734-02de8aa2db3d
|
||||||
@ -76,8 +76,8 @@ require (
|
|||||||
go4.org v0.0.0-20190313082347-94abd6928b1d // indirect
|
go4.org v0.0.0-20190313082347-94abd6928b1d // indirect
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect
|
||||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 // indirect
|
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 // indirect
|
||||||
golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa // indirect
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect
|
||||||
golang.org/x/tools v0.0.0-20190806215303-88ddfcebc769 // indirect
|
golang.org/x/sys v0.0.0-20190730183949-1393eb018365 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7
|
||||||
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8
|
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8
|
||||||
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 // indirect
|
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 // indirect
|
||||||
|
@ -3,12 +3,12 @@ package sectorbuilder
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: really need to get a callbacks API from the rust-sectorbuilder
|
// TODO: really need to get a callbacks API from the rust-sectorbuilder
|
||||||
func (sb *SectorBuilder) pollForSealedSectors(ctx context.Context) {
|
func (sb *SectorBuilder) pollForSealedSectors(ctx context.Context) {
|
||||||
|
log.Info("starting sealed sector poller")
|
||||||
|
defer log.Info("leaving sealed sector polling routine")
|
||||||
watching := make(map[uint64]bool)
|
watching := make(map[uint64]bool)
|
||||||
|
|
||||||
staged, err := sb.GetAllStagedSectors()
|
staged, err := sb.GetAllStagedSectors()
|
||||||
@ -33,9 +33,11 @@ func (sb *SectorBuilder) pollForSealedSectors(ctx context.Context) {
|
|||||||
log.Errorf("in loop: failed to get staged sectors: %s", err)
|
log.Errorf("in loop: failed to get staged sectors: %s", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
log.Info("num staged sectors: ", len(staged))
|
||||||
for _, s := range staged {
|
for _, s := range staged {
|
||||||
watching[s.SectorID] = true
|
watching[s.SectorID] = true
|
||||||
}
|
}
|
||||||
|
log.Info("len watching: ", len(watching))
|
||||||
|
|
||||||
for s := range watching {
|
for s := range watching {
|
||||||
status, err := sb.SealStatus(s)
|
status, err := sb.SealStatus(s)
|
||||||
@ -44,6 +46,7 @@ func (sb *SectorBuilder) pollForSealedSectors(ctx context.Context) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Infof("sector %d has status %d", s, status.SealStatusCode)
|
||||||
if status.SealStatusCode == 0 { // constant pls, zero implies the last step?
|
if status.SealStatusCode == 0 { // constant pls, zero implies the last step?
|
||||||
delete(watching, s)
|
delete(watching, s)
|
||||||
sb.sschan <- status
|
sb.sschan <- status
|
||||||
|
@ -7,8 +7,12 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/go-lotus/chain/address"
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
|
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
|
||||||
|
|
||||||
|
logging "github.com/ipfs/go-log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var log = logging.Logger("sectorbuilder")
|
||||||
|
|
||||||
type SectorSealingStatus = sectorbuilder.SectorSealingStatus
|
type SectorSealingStatus = sectorbuilder.SectorSealingStatus
|
||||||
|
|
||||||
type StagedSectorMetadata = sectorbuilder.StagedSectorMetadata
|
type StagedSectorMetadata = sectorbuilder.StagedSectorMetadata
|
||||||
@ -39,6 +43,7 @@ func New(cfg *SectorBuilderConfig) (*SectorBuilder, error) {
|
|||||||
|
|
||||||
return &SectorBuilder{
|
return &SectorBuilder{
|
||||||
handle: sbp,
|
handle: sbp,
|
||||||
|
sschan: make(chan SectorSealingStatus, 32),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ func Online() Option {
|
|||||||
|
|
||||||
// Storage miner
|
// Storage miner
|
||||||
ApplyIf(func(s *Settings) bool { return s.nodeType == nodeStorageMiner },
|
ApplyIf(func(s *Settings) bool { return s.nodeType == nodeStorageMiner },
|
||||||
Override(new(*sectorbuilder.SectorBuilder), sectorbuilder.New),
|
Override(new(*sectorbuilder.SectorBuilder), modules.SectorBuilder),
|
||||||
Override(new(*storage.Miner), modules.StorageMiner),
|
Override(new(*storage.Miner), modules.StorageMiner),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -100,6 +100,31 @@ func (a *FullNodeAPI) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) (*
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *FullNodeAPI) ChainGetBlockReceipts(ctx context.Context, bcid cid.Cid) ([]*types.MessageReceipt, error) {
|
||||||
|
b, err := a.Chain.GetBlock(bcid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: need to get the number of messages better than this
|
||||||
|
bm, sm, err := a.Chain.MessagesForBlock(b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var out []*types.MessageReceipt
|
||||||
|
for i := 0; i < len(bm)+len(sm); i++ {
|
||||||
|
r, err := a.Chain.GetReceipt(b, i)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
out = append(out, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *FullNodeAPI) ChainCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) {
|
func (a *FullNodeAPI) ChainCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) {
|
||||||
if ts == nil {
|
if ts == nil {
|
||||||
ts = a.Chain.GetHeaviestTipSet()
|
ts = a.Chain.GetHeaviestTipSet()
|
||||||
@ -240,6 +265,8 @@ func (a *FullNodeAPI) StateMinerSectors(ctx context.Context, addr address.Addres
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Info("miner sector count: ", minerState.SectorSetSize)
|
||||||
|
|
||||||
var sinfos []*api.SectorInfo
|
var sinfos []*api.SectorInfo
|
||||||
// Note to self: the hamt isnt a great data structure to use here... need to implement the sector set
|
// Note to self: the hamt isnt a great data structure to use here... need to implement the sector set
|
||||||
err = nd.ForEach(ctx, func(k string, val interface{}) error {
|
err = nd.ForEach(ctx, func(k string, val interface{}) error {
|
||||||
|
@ -76,6 +76,7 @@ func StorageMiner(mctx helpers.MetricsCtx, lc fx.Lifecycle, api api.FullNode, h
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Infof("setting up miner: %s", maddr)
|
||||||
sm, err := storage.NewMiner(api, maddr, h, ds, sb, w)
|
sm, err := storage.NewMiner(api, maddr, h, ds, sb, w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -73,15 +73,18 @@ func (m *Miner) Run(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *Miner) handlePostingSealedSectors(ctx context.Context) {
|
func (m *Miner) handlePostingSealedSectors(ctx context.Context) {
|
||||||
|
defer log.Info("leaving handle posting sealed sectors routine")
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case sinfo, ok := <-m.sb.SealedSectorChan():
|
case sinfo, ok := <-m.sb.SealedSectorChan():
|
||||||
|
log.Info("got a sealed sector notification!")
|
||||||
if !ok {
|
if !ok {
|
||||||
// TODO: set some state variable so that this state can be
|
// TODO: set some state variable so that this state can be
|
||||||
// visible via some status command
|
// visible via some status command
|
||||||
log.Warning("sealed sector channel closed, aborting process")
|
log.Warning("sealed sector channel closed, aborting process")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
log.Info("about to send commit sector message: ", sinfo.SectorID, m.maddr)
|
||||||
|
|
||||||
if err := m.commitSector(ctx, sinfo); err != nil {
|
if err := m.commitSector(ctx, sinfo); err != nil {
|
||||||
log.Errorf("failed to commit sector: %s", err)
|
log.Errorf("failed to commit sector: %s", err)
|
||||||
@ -114,7 +117,7 @@ func (m *Miner) commitSector(ctx context.Context, sinfo sectorbuilder.SectorSeal
|
|||||||
Method: actors.MAMethods.CommitSector,
|
Method: actors.MAMethods.CommitSector,
|
||||||
Params: enc,
|
Params: enc,
|
||||||
Value: types.NewInt(0), // TODO: need to ensure sufficient collateral
|
Value: types.NewInt(0), // TODO: need to ensure sufficient collateral
|
||||||
GasLimit: types.NewInt(10000 /* i dont know help */),
|
GasLimit: types.NewInt(1000 /* i dont know help */),
|
||||||
GasPrice: types.NewInt(1),
|
GasPrice: types.NewInt(1),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user