package filcns import ( "context" "github.com/ipfs/go-cid" "golang.org/x/xerrors" "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 api.Wallet, bt *api.BlockTemplate) (*types.FullBlock, error) { pts, err := filec.sm.ChainStore().LoadTipSet(bt.Parents) if err != nil { return nil, xerrors.Errorf("failed to load parent tipset: %w", err) } st, recpts, err := filec.sm.TipSetState(ctx, pts) if err != nil { return nil, xerrors.Errorf("failed to load tipset state: %w", err) } _, lbst, err := stmgr.GetLookbackTipSetForRound(ctx, filec.sm, pts, bt.Epoch) if err != nil { return nil, xerrors.Errorf("getting lookback miner actor state: %w", err) } worker, err := stmgr.GetMinerWorkerRaw(ctx, filec.sm, lbst, bt.Miner) if err != nil { return nil, xerrors.Errorf("failed to get miner worker: %w", err) } next := &types.BlockHeader{ Miner: bt.Miner, Parents: bt.Parents.Cids(), Ticket: bt.Ticket, ElectionProof: bt.Eproof, BeaconEntries: bt.BeaconValues, Height: bt.Epoch, Timestamp: bt.Timestamp, WinPoStProof: bt.WinningPoStProof, ParentStateRoot: st, ParentMessageReceipts: recpts, } var blsMessages []*types.Message var secpkMessages []*types.SignedMessage var blsMsgCids, secpkMsgCids []cid.Cid var blsSigs []crypto.Signature for _, msg := range bt.Messages { if msg.Signature.Type == crypto.SigTypeBLS { blsSigs = append(blsSigs, msg.Signature) blsMessages = append(blsMessages, &msg.Message) c, err := filec.sm.ChainStore().PutMessage(&msg.Message) if err != nil { return nil, err } blsMsgCids = append(blsMsgCids, c) } else if msg.Signature.Type == crypto.SigTypeSecp256k1 { c, err := filec.sm.ChainStore().PutMessage(msg) if err != nil { return nil, err } secpkMsgCids = append(secpkMsgCids, c) secpkMessages = append(secpkMessages, msg) } else { return nil, xerrors.Errorf("unknown sig type: %d", msg.Signature.Type) } } store := filec.sm.ChainStore().ActorStore(ctx) blsmsgroot, err := consensus.ToMessagesArray(store, blsMsgCids) if err != nil { return nil, xerrors.Errorf("building bls amt: %w", err) } secpkmsgroot, err := consensus.ToMessagesArray(store, secpkMsgCids) if err != nil { return nil, xerrors.Errorf("building secpk amt: %w", err) } mmcid, err := store.Put(store.Context(), &types.MsgMeta{ BlsMessages: blsmsgroot, SecpkMessages: secpkmsgroot, }) if err != nil { return nil, err } next.Messages = mmcid aggSig, err := consensus.AggregateSignatures(blsSigs) if err != nil { return nil, err } next.BLSAggregate = aggSig pweight, err := filec.sm.ChainStore().Weight(ctx, pts) if err != nil { return nil, err } next.ParentWeight = pweight baseFee, err := filec.sm.ChainStore().ComputeBaseFee(ctx, pts) if err != nil { return nil, xerrors.Errorf("computing base fee: %w", err) } next.ParentBaseFee = baseFee nosigbytes, err := next.SigningBytes() if err != nil { 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, }) if err != nil { return nil, xerrors.Errorf("failed to sign new block: %w", err) } next.BlockSig = sig fullBlock := &types.FullBlock{ Header: next, BlsMessages: blsMessages, SecpkMessages: secpkMessages, } return fullBlock, nil }