chaingen: Add revocation mungers.
This adds two new chain generator mungers for use in tests: - ReplaceRevocationVersions returns a function that itself takes a block and modifies it by replacing the transaction version of all revocations contained in the block - CreateRevocationsForMissedTickets returns a function that itself takes a block and modifies it by creating revocations for all tickets that would otherwise become missed as of that block
This commit is contained in:
parent
70edb35d0d
commit
90308ef7c2
@ -1716,6 +1716,72 @@ func ReplaceVotes(voteBits uint16, newVersion uint32) func(*wire.MsgBlock) {
|
||||
}
|
||||
}
|
||||
|
||||
// ReplaceRevocationVersions returns a function that itself takes a block and
|
||||
// modifies it by replacing the transaction version of all revocations contained
|
||||
// in the block.
|
||||
func ReplaceRevocationVersions(newVersion uint16) func(*wire.MsgBlock) {
|
||||
return func(b *wire.MsgBlock) {
|
||||
for _, stx := range b.STransactions {
|
||||
if isRevocationTx(stx) {
|
||||
stx.Version = newVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CreateRevocationsForMissedTickets returns a function that itself takes a
|
||||
// block and modifies it by creating revocations for all tickets that would
|
||||
// otherwise become missed as of that block.
|
||||
//
|
||||
// Note: This is intended to be used when the automatic ticket revocations
|
||||
// agenda is active. If the agenda is not active, revocations are not valid
|
||||
// until the block AFTER they become missed or expired.
|
||||
func (g *Generator) CreateRevocationsForMissedTickets() func(*wire.MsgBlock) {
|
||||
return func(b *wire.MsgBlock) {
|
||||
// Attempt to prevent misuse of this function by ensuring the provided block
|
||||
// connects to the current tip.
|
||||
if b.Header.PrevBlock != g.tip.BlockHash() {
|
||||
panic(fmt.Sprintf("attempted to create revocations for missed tickets "+
|
||||
"for block %s with parent %s that is not the current tip %s",
|
||||
b.BlockHash(), b.Header.PrevBlock, g.tip.BlockHash()))
|
||||
}
|
||||
|
||||
// Create a map of the ticket hashes of votes in the block for faster
|
||||
// lookup.
|
||||
const ticketInIdx = 1
|
||||
ticketsPerBlock := g.params.TicketsPerBlock
|
||||
voteTicketHashes := make(map[chainhash.Hash]struct{}, ticketsPerBlock)
|
||||
for _, stx := range b.STransactions {
|
||||
if isVoteTx(stx) {
|
||||
ticketHash := stx.TxIn[ticketInIdx].PreviousOutPoint.Hash
|
||||
voteTicketHashes[ticketHash] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the winning tickets for the block.
|
||||
prevBlock := g.blocks[b.Header.PrevBlock]
|
||||
winners, _, err := winningTickets(prevBlock, g.liveTickets, ticketsPerBlock)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Create revocation transactions for all tickets that would become missed
|
||||
// as of this block due to not having corresponding vote transaction.
|
||||
for _, winningStakeTx := range winners {
|
||||
if _, ok := voteTicketHashes[winningStakeTx.tx.TxHash()]; !ok {
|
||||
// Create a revocation from the ticket and set the signature script to
|
||||
// nil since a non-empty signature script is not allowed when the
|
||||
// automatic ticket revocations agenda is active.
|
||||
revocationTx := g.createRevocationTxFromTicket(winningStakeTx)
|
||||
revocationTx.TxIn[0].SignatureScript = nil
|
||||
|
||||
b.STransactions = append(b.STransactions, revocationTx)
|
||||
b.Header.Revocations++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CreateSpendTx creates a transaction that spends from the provided spendable
|
||||
// output and includes an additional unique OP_RETURN output to ensure the
|
||||
// transaction ends up with a unique hash. The public key script is a simple
|
||||
|
||||
Loading…
Reference in New Issue
Block a user