Skip to content

Commit

Permalink
Merge pull request #90 from SiaFoundation/nate/fix-miner-panic
Browse files Browse the repository at this point in the history
fix panic when mining v2 transactions at the allow height
  • Loading branch information
n8maninger authored Aug 23, 2024
2 parents 1c4c895 + 8e95477 commit f8e03cc
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 13 deletions.
19 changes: 10 additions & 9 deletions miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,10 @@ retry:
}},
}

if cs.Index.Height >= cs.Network.HardforkV2.AllowHeight {
childHeight := cs.Index.Height + 1
if childHeight >= cs.Network.HardforkV2.AllowHeight {
b.V2 = &types.V2BlockData{
Height: cs.Index.Height + 1,
Height: childHeight,
}
}

Expand All @@ -69,14 +70,14 @@ retry:
b.Transactions = append(b.Transactions, txn)
b.MinerPayouts[0].Value = b.MinerPayouts[0].Value.Add(txn.TotalFees())
}
for _, txn := range v2Txns {
if weight += cs.V2TransactionWeight(txn); weight > cs.MaxBlockWeight() {
break
}
b.V2.Transactions = append(b.V2.Transactions, txn)
b.MinerPayouts[0].Value = b.MinerPayouts[0].Value.Add(txn.MinerFee)
}
if b.V2 != nil {
for _, txn := range v2Txns {
if weight += cs.V2TransactionWeight(txn); weight > cs.MaxBlockWeight() {
break
}
b.V2.Transactions = append(b.V2.Transactions, txn)
b.MinerPayouts[0].Value = b.MinerPayouts[0].Value.Add(txn.MinerFee)
}
b.V2.Commitment = cs.Commitment(cs.TransactionsCommitment(b.Transactions, b.V2Transactions()), addr)
}
found := FindBlockNonce(cs, &b, timeout)
Expand Down
92 changes: 88 additions & 4 deletions miner_test.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package coreutils
package coreutils_test

import (
"testing"
"time"

"go.sia.tech/core/types"
"go.sia.tech/coreutils"
"go.sia.tech/coreutils/chain"
"go.sia.tech/coreutils/testutil"
)

func TestMiner(t *testing.T) {
n, genesisBlock := chain.TestnetZen()
n.InitialTarget = types.BlockID{0xFF}
n, genesisBlock := testutil.Network()

sk := types.GeneratePrivateKey()
genesisBlock.Transactions = []types.Transaction{{
Expand Down Expand Up @@ -59,7 +60,7 @@ func TestMiner(t *testing.T) {
}

// assert the minerpayout includes the txn fee
b, found := MineBlock(cm, types.VoidAddress, time.Second)
b, found := coreutils.MineBlock(cm, types.VoidAddress, time.Second)
if !found {
t.Fatal("PoW failed")
} else if len(b.MinerPayouts) != 1 {
Expand All @@ -68,3 +69,86 @@ func TestMiner(t *testing.T) {
t.Fatal("unexpected miner payout", b.MinerPayouts[0].Value.ExactString())
}
}

func TestV2MineBlocks(t *testing.T) {
n, genesisBlock := testutil.V2Network()
n.HardforkV2.AllowHeight = 5
n.HardforkV2.RequireHeight = 10
n.InitialTarget = types.BlockID{0xFF}

genesisBlock.Transactions = []types.Transaction{{
SiacoinOutputs: []types.SiacoinOutput{
{
Address: types.AnyoneCanSpend().Address(),
Value: types.Siacoins(10),
},
},
}}

store, tipState, err := chain.NewDBStore(chain.NewMemDB(), n, genesisBlock)
if err != nil {
t.Fatal(err)
}
cm := chain.NewManager(store, tipState)

mineBlocks := func(t *testing.T, n int) {
for ; n > 0; n-- {
b, ok := coreutils.MineBlock(cm, types.VoidAddress, time.Second)
if !ok {
t.Fatal("failed to mine block")
} else if err := cm.AddBlocks([]types.Block{b}); err != nil {
t.Fatal(err)
}
}
}

// mine until just before the allow height
mineBlocks(t, 4)

elements := make(map[types.Hash256]types.SiacoinElement)
_, applied, err := cm.UpdatesSince(types.ChainIndex{}, 500)
if err != nil {
t.Fatal(err)
}
for _, cau := range applied {
cau.ForEachSiacoinElement(func(sce types.SiacoinElement, created, spent bool) {
switch {
case created && spent:
return
case sce.SiacoinOutput.Address != types.AnyoneCanSpend().Address():
return
case created:
elements[sce.ID] = sce
case spent:
delete(elements, sce.ID)
}
})

for k, v := range elements {
cau.UpdateElementProof(&v.StateElement)
elements[k] = v
}
}

var se types.SiacoinElement
for _, v := range elements {
se = v
break
}

txn := types.V2Transaction{
MinerFee: se.SiacoinOutput.Value,
SiacoinInputs: []types.V2SiacoinInput{{
Parent: se,
SatisfiedPolicy: types.SatisfiedPolicy{Policy: types.AnyoneCanSpend()},
}},
}

// add the transaction to the pool
_, err = cm.AddV2PoolTransactions(cm.Tip(), []types.V2Transaction{txn})
if err != nil {
t.Fatal(err)
}

mineBlocks(t, 1)
}

0 comments on commit f8e03cc

Please sign in to comment.