2019-07-25 22:15:33 +00:00
|
|
|
package gen
|
2019-07-05 14:46:21 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2019-09-06 20:03:28 +00:00
|
|
|
|
2020-09-07 03:49:10 +00:00
|
|
|
"github.com/filecoin-project/go-state-types/crypto"
|
2020-10-08 01:09:33 +00:00
|
|
|
blockadt "github.com/filecoin-project/specs-actors/actors/util/adt"
|
2019-09-06 20:03:28 +00:00
|
|
|
cid "github.com/ipfs/go-cid"
|
2019-09-17 01:56:37 +00:00
|
|
|
cbg "github.com/whyrusleeping/cbor-gen"
|
2019-08-27 00:46:39 +00:00
|
|
|
"golang.org/x/xerrors"
|
2019-07-08 15:14:36 +00:00
|
|
|
|
2020-04-09 00:24:10 +00:00
|
|
|
"github.com/filecoin-project/lotus/api"
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
2020-07-26 01:38:18 +00:00
|
|
|
"github.com/filecoin-project/lotus/lib/sigs/bls"
|
2019-07-05 14:46:21 +00:00
|
|
|
)
|
|
|
|
|
2020-10-08 23:27:38 +00:00
|
|
|
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w api.WalletAPI, bt *api.BlockTemplate) (*types.FullBlock, error) {
|
2020-04-08 19:06:41 +00:00
|
|
|
|
2020-04-09 00:24:10 +00:00
|
|
|
pts, err := sm.ChainStore().LoadTipSet(bt.Parents)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to load parent tipset: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
st, recpts, err := sm.TipSetState(ctx, pts)
|
2019-07-05 14:46:21 +00:00
|
|
|
if err != nil {
|
2019-11-13 23:35:58 +00:00
|
|
|
return nil, xerrors.Errorf("failed to load tipset state: %w", err)
|
2019-07-05 14:46:21 +00:00
|
|
|
}
|
|
|
|
|
2020-10-21 23:08:24 +00:00
|
|
|
lbts, err := stmgr.GetLookbackTipSetForRound(ctx, sm, pts, bt.Epoch)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("getting lookback miner actor state: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
lbst, _, err := sm.TipSetState(ctx, lbts)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
worker, err := stmgr.GetMinerWorkerRaw(ctx, sm, lbst, bt.Miner)
|
2019-08-27 00:46:39 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to get miner worker: %w", err)
|
|
|
|
}
|
2019-07-05 14:46:21 +00:00
|
|
|
|
2019-07-25 22:15:03 +00:00
|
|
|
next := &types.BlockHeader{
|
2020-04-09 00:24:10 +00:00
|
|
|
Miner: bt.Miner,
|
|
|
|
Parents: bt.Parents.Cids(),
|
|
|
|
Ticket: bt.Ticket,
|
|
|
|
ElectionProof: bt.Eproof,
|
|
|
|
|
2020-04-17 22:02:43 +00:00
|
|
|
BeaconEntries: bt.BeaconValues,
|
|
|
|
Height: bt.Epoch,
|
|
|
|
Timestamp: bt.Timestamp,
|
|
|
|
WinPoStProof: bt.WinningPoStProof,
|
2019-09-27 23:55:15 +00:00
|
|
|
ParentStateRoot: st,
|
|
|
|
ParentMessageReceipts: recpts,
|
2019-07-05 14:46:21 +00:00
|
|
|
}
|
|
|
|
|
2019-08-01 20:40:47 +00:00
|
|
|
var blsMessages []*types.Message
|
|
|
|
var secpkMessages []*types.SignedMessage
|
|
|
|
|
|
|
|
var blsMsgCids, secpkMsgCids []cid.Cid
|
2020-02-12 23:52:36 +00:00
|
|
|
var blsSigs []crypto.Signature
|
2020-04-09 00:24:10 +00:00
|
|
|
for _, msg := range bt.Messages {
|
2020-02-12 23:52:36 +00:00
|
|
|
if msg.Signature.Type == crypto.SigTypeBLS {
|
2019-07-05 14:46:21 +00:00
|
|
|
blsSigs = append(blsSigs, msg.Signature)
|
2019-08-01 20:40:47 +00:00
|
|
|
blsMessages = append(blsMessages, &msg.Message)
|
2019-07-05 14:46:21 +00:00
|
|
|
|
2019-09-06 06:26:02 +00:00
|
|
|
c, err := sm.ChainStore().PutMessage(&msg.Message)
|
2019-07-05 14:46:21 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-08-01 20:40:47 +00:00
|
|
|
blsMsgCids = append(blsMsgCids, c)
|
2019-07-05 14:46:21 +00:00
|
|
|
} else {
|
2019-10-05 23:18:39 +00:00
|
|
|
c, err := sm.ChainStore().PutMessage(msg)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
secpkMsgCids = append(secpkMsgCids, c)
|
2019-08-01 20:40:47 +00:00
|
|
|
secpkMessages = append(secpkMessages, msg)
|
2019-10-05 23:18:39 +00:00
|
|
|
|
2019-07-05 14:46:21 +00:00
|
|
|
}
|
2019-08-01 20:40:47 +00:00
|
|
|
}
|
|
|
|
|
2020-07-23 00:14:54 +00:00
|
|
|
store := sm.ChainStore().Store(ctx)
|
|
|
|
blsmsgroot, err := toArray(store, blsMsgCids)
|
2019-08-01 20:40:47 +00:00
|
|
|
if err != nil {
|
2019-09-17 01:56:37 +00:00
|
|
|
return nil, xerrors.Errorf("building bls amt: %w", err)
|
2019-08-01 20:40:47 +00:00
|
|
|
}
|
2020-07-23 00:14:54 +00:00
|
|
|
secpkmsgroot, err := toArray(store, secpkMsgCids)
|
2019-08-01 20:40:47 +00:00
|
|
|
if err != nil {
|
2019-09-17 01:56:37 +00:00
|
|
|
return nil, xerrors.Errorf("building secpk amt: %w", err)
|
2019-08-01 20:40:47 +00:00
|
|
|
}
|
|
|
|
|
2020-07-23 00:14:54 +00:00
|
|
|
mmcid, err := store.Put(store.Context(), &types.MsgMeta{
|
2019-08-01 20:40:47 +00:00
|
|
|
BlsMessages: blsmsgroot,
|
|
|
|
SecpkMessages: secpkmsgroot,
|
|
|
|
})
|
2019-07-05 14:46:21 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-08-01 20:40:47 +00:00
|
|
|
next.Messages = mmcid
|
2019-07-05 14:46:21 +00:00
|
|
|
|
|
|
|
aggSig, err := aggregateSignatures(blsSigs)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
next.BLSAggregate = aggSig
|
2020-04-09 00:24:10 +00:00
|
|
|
pweight, err := sm.ChainStore().Weight(ctx, pts)
|
2019-10-15 05:00:30 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
next.ParentWeight = pweight
|
2019-07-05 14:46:21 +00:00
|
|
|
|
2020-08-06 17:09:03 +00:00
|
|
|
baseFee, err := sm.ChainStore().ComputeBaseFee(ctx, pts)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("computing base fee: %w", err)
|
|
|
|
}
|
|
|
|
next.ParentBaseFee = baseFee
|
|
|
|
|
2019-10-03 19:45:14 +00:00
|
|
|
nosigbytes, err := next.SigningBytes()
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to get signing bytes for block: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-10-14 00:44:42 +00:00
|
|
|
sig, err := w.WalletSign(ctx, worker, nosigbytes, api.MsgMeta{
|
2020-10-08 23:27:49 +00:00
|
|
|
Type: api.MTBlock,
|
2020-10-08 23:27:38 +00:00
|
|
|
})
|
2019-08-27 00:46:39 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to sign new block: %w", err)
|
|
|
|
}
|
|
|
|
|
2019-11-19 20:05:21 +00:00
|
|
|
next.BlockSig = sig
|
2019-08-27 00:46:39 +00:00
|
|
|
|
2019-07-25 22:15:03 +00:00
|
|
|
fullBlock := &types.FullBlock{
|
2019-08-01 20:40:47 +00:00
|
|
|
Header: next,
|
|
|
|
BlsMessages: blsMessages,
|
|
|
|
SecpkMessages: secpkMessages,
|
2019-07-05 14:46:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return fullBlock, nil
|
|
|
|
}
|
|
|
|
|
2020-03-21 22:25:00 +00:00
|
|
|
func aggregateSignatures(sigs []crypto.Signature) (*crypto.Signature, error) {
|
2020-07-26 01:38:18 +00:00
|
|
|
sigsS := make([][]byte, len(sigs))
|
|
|
|
for i := 0; i < len(sigs); i++ {
|
|
|
|
sigsS[i] = sigs[i].Data
|
2019-07-05 14:46:21 +00:00
|
|
|
}
|
|
|
|
|
2020-07-26 01:38:18 +00:00
|
|
|
aggregator := new(bls.AggregateSignature).AggregateCompressed(sigsS)
|
|
|
|
if aggregator == nil {
|
2020-06-26 18:32:47 +00:00
|
|
|
if len(sigs) > 0 {
|
|
|
|
return nil, xerrors.Errorf("bls.Aggregate returned nil with %d signatures", len(sigs))
|
|
|
|
}
|
|
|
|
|
2020-07-26 04:46:23 +00:00
|
|
|
// Note: for blst this condition should not happen - nil should not
|
|
|
|
// be returned
|
2020-06-26 18:32:47 +00:00
|
|
|
return &crypto.Signature{
|
|
|
|
Type: crypto.SigTypeBLS,
|
2020-07-26 01:38:18 +00:00
|
|
|
Data: new(bls.Signature).Compress(),
|
2020-06-26 18:32:47 +00:00
|
|
|
}, nil
|
|
|
|
}
|
2020-07-26 04:46:23 +00:00
|
|
|
aggSigAff := aggregator.ToAffine()
|
|
|
|
if aggSigAff == nil {
|
|
|
|
return &crypto.Signature{
|
|
|
|
Type: crypto.SigTypeBLS,
|
|
|
|
Data: new(bls.Signature).Compress(),
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
aggSig := aggSigAff.Compress()
|
2020-03-21 22:25:00 +00:00
|
|
|
return &crypto.Signature{
|
2020-02-12 23:52:36 +00:00
|
|
|
Type: crypto.SigTypeBLS,
|
2020-07-26 01:38:18 +00:00
|
|
|
Data: aggSig,
|
2019-07-05 14:46:21 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2020-10-08 01:09:33 +00:00
|
|
|
func toArray(store blockadt.Store, cids []cid.Cid) (cid.Cid, error) {
|
|
|
|
arr := blockadt.MakeEmptyArray(store)
|
2020-07-23 00:14:54 +00:00
|
|
|
for i, c := range cids {
|
2019-09-17 01:56:37 +00:00
|
|
|
oc := cbg.CborCid(c)
|
2020-07-23 00:14:54 +00:00
|
|
|
if err := arr.Set(uint64(i), &oc); err != nil {
|
|
|
|
return cid.Undef, err
|
|
|
|
}
|
2019-07-05 14:46:21 +00:00
|
|
|
}
|
2020-07-23 00:14:54 +00:00
|
|
|
return arr.Root()
|
2019-07-05 14:46:21 +00:00
|
|
|
}
|