diff --git a/miner.go b/miner.go index 28f1126..fef434e 100644 --- a/miner.go +++ b/miner.go @@ -53,6 +53,7 @@ func MineBlock(cm *chain.Manager, addr types.Address, timeout time.Duration) (ty break } b.Transactions = append(b.Transactions, txn) + b.MinerPayouts[0].Value = b.MinerPayouts[0].Value.Add(txn.TotalFees()) } for _, txn := range cm.V2PoolTransactions() { if weight += cs.V2TransactionWeight(txn); weight > cs.MaxBlockWeight() { @@ -64,6 +65,7 @@ func MineBlock(cm *chain.Manager, addr types.Address, timeout time.Duration) (ty } } b.V2.Transactions = append(b.V2.Transactions, txn) + b.MinerPayouts[0].Value = b.MinerPayouts[0].Value.Add(txn.MinerFee) } if b.V2 != nil { b.V2.Commitment = cs.Commitment(cs.TransactionsCommitment(b.Transactions, b.V2Transactions()), addr) diff --git a/miner_test.go b/miner_test.go new file mode 100644 index 0000000..c25b4f8 --- /dev/null +++ b/miner_test.go @@ -0,0 +1,71 @@ +package coreutils + +import ( + "testing" + "time" + + "go.sia.tech/core/types" + "go.sia.tech/coreutils/chain" +) + +func TestMiner(t *testing.T) { + n, genesisBlock := chain.TestnetZen() + n.InitialTarget = types.BlockID{0xFF} + + sk := types.GeneratePrivateKey() + genesisBlock.Transactions = []types.Transaction{{ + SiacoinOutputs: []types.SiacoinOutput{ + { + Address: types.StandardUnlockHash(sk.PublicKey()), + Value: types.Siacoins(10), + }, + }, + }} + + store, tipState, err := chain.NewDBStore(chain.NewMemDB(), n, genesisBlock) + if err != nil { + t.Fatal(err) + } + defer store.Close() + cm := chain.NewManager(store, tipState) + + // create a transaction + txn := types.Transaction{ + SiacoinInputs: []types.SiacoinInput{{ + ParentID: genesisBlock.Transactions[0].SiacoinOutputID(0), + UnlockConditions: types.StandardUnlockConditions(sk.PublicKey()), + }}, + SiacoinOutputs: []types.SiacoinOutput{{ + Address: types.StandardUnlockHash(sk.PublicKey()), + Value: types.Siacoins(9), + }}, + MinerFees: []types.Currency{types.Siacoins(1)}, + } + + // sign the inputs + for _, sci := range txn.SiacoinInputs { + sig := sk.SignHash(cm.TipState().WholeSigHash(txn, types.Hash256(sci.ParentID), 0, 0, nil)) + txn.Signatures = append(txn.Signatures, types.TransactionSignature{ + ParentID: types.Hash256(sci.ParentID), + CoveredFields: types.CoveredFields{WholeTransaction: true}, + PublicKeyIndex: 0, + Signature: sig[:], + }) + } + + // add the transaction to the pool + _, err = cm.AddPoolTransactions([]types.Transaction{txn}) + if err != nil { + t.Fatal(err) + } + + // assert the minerpayout includes the txn fee + b, found := MineBlock(cm, types.VoidAddress, time.Second) + if !found { + t.Fatal("PoW failed") + } else if len(b.MinerPayouts) != 1 { + t.Fatal("expected one miner payout") + } else if b.MinerPayouts[0].Value.Cmp(types.Siacoins(1).Add(cm.TipState().BlockReward())) != 0 { + t.Fatal("unexpected miner payout", b.MinerPayouts[0].Value.ExactString()) + } +}