blockchain: Add calcTicketReturnAmounts tests.

This adds full test coverage for the calcTicketReturnAmounts function
to ensure that ticket return amounts are calculated correctly under a
variety of conditions.
This commit is contained in:
Ryan Staudt 2021-08-22 05:55:26 -05:00 committed by Dave Collins
parent 75c9844599
commit db7b0decfd

View File

@ -9,15 +9,19 @@ import (
"bytes"
"compress/bzip2"
"context"
"encoding/binary"
"encoding/gob"
"encoding/hex"
"errors"
"fmt"
mrand "math/rand"
"os"
"path/filepath"
"reflect"
"testing"
"time"
"github.com/decred/dcrd/blockchain/stake/v4"
"github.com/decred/dcrd/blockchain/v4/chaingen"
"github.com/decred/dcrd/chaincfg/chainhash"
"github.com/decred/dcrd/chaincfg/v3"
@ -1351,3 +1355,214 @@ func TestExplicitVerUpgradesSemantics(t *testing.T) {
g.AcceptTipBlock()
}
// TestCalcTicketReturnAmounts ensures that ticket return amounts are calculated
// correctly under a variety of conditions.
func TestCalcTicketReturnAmounts(t *testing.T) {
t.Parallel()
// Default header bytes for tests.
prevHeaderBytes, _ := hex.DecodeString("07000000dc02335daa073d293e1b150648f" +
"0444a60b9c97604abd01e00000000000000003c449b2321c4bd0d1fa76ed59f80ebaf46f" +
"16cfb2d17ba46948f09f21861095566482410a463ed49473c27278cd7a2a3712a3b19ff1" +
"f6225717d3eb71cc2b5590100012c7312a3c30500050095a100000cf42418f1820a87030" +
"0000020a10700091600005b32a55f5bcce31078832100007469943958002e00000000000" +
"0000000000000000000000000000007000000")
// Default ticket commitment script hex for tests.
p2pkhCommitScriptHex := "ba76a914097e847d49c6806f6933e806a350f43b97ac70d088ac"
// createTestTicketOuts is a helper function that creates mock minimal outputs
// for a ticket with the given contribution amounts. Note that this only
// populates the ticket commitment outputs since those are the only outputs
// used to calculate ticket return amounts.
createTestTicketOuts := func(contribAmounts []int64) []*stake.MinimalOutput {
ticketOuts := make([]*stake.MinimalOutput, len(contribAmounts)*2+1)
for i := 0; i < len(contribAmounts); i++ {
commitScript := hexToBytes(p2pkhCommitScriptHex)
amtBytes := commitScript[commitAmountStartIdx:commitAmountEndIdx]
binary.LittleEndian.PutUint64(amtBytes, uint64(contribAmounts[i]))
ticketOuts[i*2+1] = &stake.MinimalOutput{PkScript: commitScript}
}
return ticketOuts
}
tests := []struct {
name string
contribAmounts []int64
ticketPurchaseAmount int64
voteSubsidy int64
prevHeaderBytes []byte
isVote bool
isAutoRevocationsEnabled bool
want []int64
}{{
name: "vote rewards - evenly divisible over all outputs (auto " +
"revocations disabled)",
contribAmounts: []int64{
2500000000,
2500000000,
5000000000,
10000000000,
},
ticketPurchaseAmount: 20000000000,
voteSubsidy: 100000000,
isVote: true,
want: []int64{
2512500000,
2512500000,
5025000000,
10050000000,
},
}, {
name: "revocation rewards - evenly divisible over all outputs (auto " +
"revocations disabled)",
contribAmounts: []int64{
2500000000,
2500000000,
5000000000,
10000000000,
},
ticketPurchaseAmount: 20000000000,
voteSubsidy: 0,
want: []int64{
2500000000,
2500000000,
5000000000,
10000000000,
},
}, {
name: "vote rewards - remainder of 2 (auto revocations disabled)",
contribAmounts: []int64{
100000000,
100000000,
100000000,
},
ticketPurchaseAmount: 300000000,
voteSubsidy: 300002,
isVote: true,
want: []int64{
100100000,
100100000,
100100000,
},
}, {
name: "revocation rewards - remainder of 4 (auto revocations disabled)",
contribAmounts: []int64{
100000000,
100000000,
100000000,
100000000,
100000000,
100000000,
100000000,
100000000,
},
ticketPurchaseAmount: 799999996,
voteSubsidy: 0,
want: []int64{
99999999,
99999999,
99999999,
99999999,
99999999,
99999999,
99999999,
99999999,
},
}, {
name: "vote rewards - evenly divisible over all outputs (auto " +
"revocations enabled)",
contribAmounts: []int64{
2500000000,
2500000000,
5000000000,
10000000000,
},
ticketPurchaseAmount: 20000000000,
voteSubsidy: 100000000,
prevHeaderBytes: prevHeaderBytes,
isVote: true,
isAutoRevocationsEnabled: true,
want: []int64{
2512500000,
2512500000,
5025000000,
10050000000,
},
}, {
name: "revocation rewards - evenly divisible over all outputs (auto " +
"revocations enabled)",
contribAmounts: []int64{
2500000000,
2500000000,
5000000000,
10000000000,
},
ticketPurchaseAmount: 20000000000,
voteSubsidy: 0,
prevHeaderBytes: prevHeaderBytes,
isAutoRevocationsEnabled: true,
want: []int64{
2500000000,
2500000000,
5000000000,
10000000000,
},
}, {
name: "vote rewards - remainder of 2 (auto revocations enabled)",
contribAmounts: []int64{
100000000,
100000000,
100000000,
100000000,
},
ticketPurchaseAmount: 400000000,
voteSubsidy: 400002,
prevHeaderBytes: prevHeaderBytes,
isVote: true,
isAutoRevocationsEnabled: true,
want: []int64{
100100000,
100100000,
100100000,
100100000,
},
}, {
name: "revocation rewards - remainder of 4 (auto revocations enabled)",
contribAmounts: []int64{
100000000,
100000000,
100000000,
100000000,
100000000,
100000000,
100000000,
100000000,
},
ticketPurchaseAmount: 799999996,
voteSubsidy: 0,
prevHeaderBytes: prevHeaderBytes,
isAutoRevocationsEnabled: true,
want: []int64{
99999999,
100000000,
99999999,
99999999,
99999999,
99999999,
100000001,
100000000,
},
}}
for _, test := range tests {
got := calcTicketReturnAmounts(createTestTicketOuts(test.contribAmounts),
test.ticketPurchaseAmount, test.voteSubsidy, test.prevHeaderBytes,
test.isVote, test.isAutoRevocationsEnabled)
if !reflect.DeepEqual(got, test.want) {
t.Errorf("%q: unexpected result -- got %v, want %v", test.name, got,
test.want)
}
}
}