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
|
|
|
|
2019-09-17 01:56:37 +00:00
|
|
|
amt "github.com/filecoin-project/go-amt-ipld"
|
2019-09-06 20:03:28 +00:00
|
|
|
bls "github.com/filecoin-project/go-bls-sigs"
|
|
|
|
cid "github.com/ipfs/go-cid"
|
|
|
|
hamt "github.com/ipfs/go-hamt-ipld"
|
2019-07-05 14:46:21 +00:00
|
|
|
"github.com/pkg/errors"
|
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
|
|
|
|
2019-07-12 23:52:25 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/actors"
|
2019-07-08 15:14:36 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/address"
|
2019-09-06 06:26:02 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/stmgr"
|
2019-07-12 10:23:05 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/types"
|
2019-07-26 04:54:22 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/vm"
|
2019-08-27 00:46:39 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/wallet"
|
2019-07-05 14:46:21 +00:00
|
|
|
)
|
|
|
|
|
2019-09-06 06:26:02 +00:00
|
|
|
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, timestamp uint64) (*types.FullBlock, error) {
|
2019-10-02 20:03:27 +00:00
|
|
|
st, recpts, err := sm.TipSetState(parents)
|
2019-07-05 14:46:21 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "failed to load tipset state")
|
|
|
|
}
|
|
|
|
|
2019-07-11 02:36:43 +00:00
|
|
|
height := parents.Height() + uint64(len(tickets))
|
2019-07-05 14:46:21 +00:00
|
|
|
|
2019-09-20 12:22:46 +00:00
|
|
|
r := vm.NewChainRand(sm.ChainStore(), parents.Cids(), parents.Height(), tickets)
|
2019-09-20 02:54:52 +00:00
|
|
|
vmi, err := vm.NewVM(st, height, r, miner, sm.ChainStore())
|
2019-07-11 02:36:43 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-07-05 14:46:21 +00:00
|
|
|
|
2019-09-06 06:26:02 +00:00
|
|
|
owner, err := stmgr.GetMinerOwner(ctx, sm, st, miner)
|
2019-08-27 00:46:39 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to get miner owner: %w", err)
|
|
|
|
}
|
|
|
|
|
2019-09-06 06:26:02 +00:00
|
|
|
worker, err := stmgr.GetMinerWorker(ctx, sm, st, miner)
|
2019-08-27 00:46:39 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to get miner worker: %w", err)
|
|
|
|
}
|
2019-09-26 22:33:38 +00:00
|
|
|
networkBalance, err := vmi.ActorBalance(actors.NetworkAddress)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to get network balance: %w", err)
|
|
|
|
}
|
2019-08-27 00:46:39 +00:00
|
|
|
|
2019-07-05 14:46:21 +00:00
|
|
|
// apply miner reward
|
2019-09-26 22:33:38 +00:00
|
|
|
if err := vmi.TransferFunds(actors.NetworkAddress, owner, vm.MiningReward(networkBalance)); err != nil {
|
2019-07-05 14:46:21 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-07-25 22:15:03 +00:00
|
|
|
next := &types.BlockHeader{
|
2019-09-27 23:55:15 +00:00
|
|
|
Miner: miner,
|
|
|
|
Parents: parents.Cids(),
|
|
|
|
Tickets: tickets,
|
|
|
|
Height: height,
|
|
|
|
Timestamp: timestamp,
|
|
|
|
ElectionProof: proof,
|
|
|
|
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
|
2019-07-24 05:38:16 +00:00
|
|
|
var blsSigs []types.Signature
|
2019-07-11 02:36:43 +00:00
|
|
|
for _, msg := range msgs {
|
2019-08-26 08:46:01 +00:00
|
|
|
if msg.Signature.TypeCode() == types.IKTBLS {
|
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-08-01 20:40:47 +00:00
|
|
|
secpkMsgCids = append(secpkMsgCids, msg.Cid())
|
|
|
|
secpkMessages = append(secpkMessages, msg)
|
2019-07-05 14:46:21 +00:00
|
|
|
}
|
2019-08-01 20:40:47 +00:00
|
|
|
}
|
|
|
|
|
2019-09-17 01:56:37 +00:00
|
|
|
bs := amt.WrapBlockstore(sm.ChainStore().Blockstore())
|
|
|
|
blsmsgroot, err := amt.FromArray(bs, toIfArr(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
|
|
|
}
|
2019-09-17 01:56:37 +00:00
|
|
|
secpkmsgroot, err := amt.FromArray(bs, toIfArr(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
|
|
|
}
|
|
|
|
|
2019-09-17 01:56:37 +00:00
|
|
|
mmcid, err := bs.Put(&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
|
2019-09-06 06:26:02 +00:00
|
|
|
pweight := sm.ChainStore().Weight(parents)
|
2019-07-12 10:23:05 +00:00
|
|
|
next.ParentWeight = types.NewInt(pweight)
|
2019-07-05 14:46:21 +00:00
|
|
|
|
2019-08-27 00:46:39 +00:00
|
|
|
// TODO: set timestamp
|
|
|
|
|
2019-09-11 20:10:29 +00:00
|
|
|
nosigbytes, err := next.SigningBytes()
|
2019-08-27 00:46:39 +00:00
|
|
|
if err != nil {
|
2019-09-11 20:10:29 +00:00
|
|
|
return nil, xerrors.Errorf("failed to get signing bytes for block: %w", err)
|
2019-08-27 00:46:39 +00:00
|
|
|
}
|
|
|
|
|
2019-09-17 01:56:37 +00:00
|
|
|
cst := hamt.CSTFromBstore(sm.ChainStore().Blockstore())
|
2019-08-27 00:46:39 +00:00
|
|
|
waddr, err := vm.ResolveToKeyAddr(vmi.StateTree(), cst, worker)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to resolve miner address to key address: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
sig, err := w.Sign(ctx, waddr, nosigbytes)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to sign new block: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
next.BlockSig = *sig
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2019-07-24 05:38:16 +00:00
|
|
|
func aggregateSignatures(sigs []types.Signature) (types.Signature, error) {
|
2019-07-05 14:46:21 +00:00
|
|
|
var blsSigs []bls.Signature
|
|
|
|
for _, s := range sigs {
|
|
|
|
var bsig bls.Signature
|
|
|
|
copy(bsig[:], s.Data)
|
|
|
|
blsSigs = append(blsSigs, bsig)
|
|
|
|
}
|
|
|
|
|
|
|
|
aggSig := bls.Aggregate(blsSigs)
|
2019-07-24 05:38:16 +00:00
|
|
|
return types.Signature{
|
|
|
|
Type: types.KTBLS,
|
2019-07-05 14:46:21 +00:00
|
|
|
Data: aggSig[:],
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2019-09-17 01:56:37 +00:00
|
|
|
func toIfArr(cids []cid.Cid) []cbg.CBORMarshaler {
|
|
|
|
out := make([]cbg.CBORMarshaler, 0, len(cids))
|
2019-07-05 14:46:21 +00:00
|
|
|
for _, c := range cids {
|
2019-09-17 01:56:37 +00:00
|
|
|
oc := cbg.CborCid(c)
|
|
|
|
out = append(out, &oc)
|
2019-07-05 14:46:21 +00:00
|
|
|
}
|
|
|
|
return out
|
|
|
|
}
|