This adds functionality to proactively evict SigCache entries when they
are nearly guaranteed to no longer be useful. It accomplishes this by
evicting entries related to transactions in the block that is 2 levels
deep from a newly processed block.
Proactively evicting entries reduces the likelihood of the SigCache
reaching maximum capacity quickly and then relying on random eviction,
which may randomly evict entries that are still useful.
This is based on https://proposals.decred.org/proposals/c96290a but was
modified in order to deal with realities that were unknown at the time
of the specification draft.
It is large and could not really be broken apart due to the pervasive
use of the isTreasuryEnabled flag. It was primarily authored by
* Marco Peereboom <marco@peereboom.us>
* Dave Collins <davec@conformal.com>
* Matheus Degiovani <opensource@matheusd.com>
With additional contributions from
* Donald Adu-Poku <donald.adu@gmail.com>
* Jamie Holdstock <jholdstock@decred.org>
Major changes:
* Add decentralized treasury agenda, as specified in DCP0006, to all supported
nets.
* Add functions to determine if the decentralized treasury agenda is active at
given block.
* Add new opcode OP_TADD that is a nop in txscript but is used to tag scripts
that credit the treasury account. This opcode is overloaded for treasurybase
and for normal transactions.
* Add new opcode OP_TSPEND that is a nop in txscript but is used to tag scripts
that debit the treasury account.
* Add new opcode OP_TGEN that is a nop in txscript but is used to tag P2PKH and
P2SH outputs in a TSpend transaction.
* Add functions that detect if a transaction is a valid TAdd, TSpend
or treasurybase transaction.
* Add error codes that return specific treasurybase/TAdd/TSpend consensus
violations.
* Modify countSpentOutputs to deal with treasury opcodes accordingly.
* Modify indexBlock to skip treasury transactions that do not have inputs.
* Add IsTreasuryEnabled call to ChainQueryer interface.
* Add treasury logger for debugging and logging the decentralized treasury
subsystem.
* Add IsTreasuryActive flag to BlockConnectedNtfnsData and
BlockDisconnectedNtfnsData.
* Modify OP_SSGEN to allow an optional output that contains votes for a TSpend
transaction hash.
* Add function that returns TSpend votes from an SSGen transaction.
* Modify CalcStakeVoteSubsidy so that treasurybase, unlike coinbase, is always
awarded the full percentage of the assigned block reward.
* Add helper functions to do all TSpend math so that callers don't roll their
own.
* Modify IsCoinBaseTx to not mistake a TSpend transaction as a coinbase.
* Add checkTreasuryBase function that verifies that a treasurybase is properly
constructed and pays the right amount to the treasury account.
* Add functions to calculate treasury balance for the provided block hash/node.
* Add function that verifies if a TSpend has a valid signature.
* Add functions to determine if a TSpend is not overspending.
* Add function to determine if a TSpend has been mined on the provided chain.
* Add functions that count and verifies treasury spend votes.
* Modify connectTransaction and disconnectTransactions to deal with the various
treasury transactions.
* Split CheckTransactionSanity in two functions
checkTransactionSanityContextFree and checkTransactionSanityContextual. This
is done in order to keep the decentralized treasury, which is always
contextual, from infecting the context free checks.
* Modify checkTransactionSanityContextual to recognize and verify treasury
transactions.
* Modify CheckTransactionSanity to deal with treasury transactions.
* Split checkBlockSanity in two functions checkBlockSanityContextFree and
checkBlockSanityContextual. This is done in order to keep the decentralized
treasury, which is always contextual, from infecting the context free checks.
* Modify checkBlockSanityContextual to enforce treasurybase and TAdd consensus
checks.
* Modify checkBlockPositional by unindenting it and adding TSpend consensus
enforcement.
* Modify checkCoinbaseUniqueHeightWithAddress to deal with the removal of the
project subsidy from output 0.
* Add checkCoinbaseUniqueHeightWithTreasuryBase that verifies coinbase and
treasurybase in the provided block.
* Unindent checkBlockContext.
* Modify checkTicketRedeemerCommitments and checkVoteInputs to deal with
potential tspend votes.
* Modify CheckTransactionInputs to skip treasurybase transactions.
* Modify CheckTransactionInputs to deal with TSpend transactions. Ensure the
provided Pi key is valid and that the signature is valid for the transaction.
Ensure that treasury TAdd and TSpend transaction utxo can only be spent after
coinbase maturity.
* Modify CountSigOps to deal with treasury transactions.
* Modify CountP2SHSigOps to deal with treasury transactions.
* Modify getStakeTreeFees to skip treasury transactions. Modify
totalOutputs to subtract ValueIn 0 for TSpend and treasurybase transactions.
* Modify checkTransactionsAndConnect to deal with modified amounts.
* Add tspendChecks function that verifies an entire TSpend transaction
validity at the point of the provided block. It ensures a TSpend is on a TVI.
It ensures the TSpend is in the valid window. It verifies that a TSpend In
and Out amounts match. It ensures a TSpend has the ValueIn amount encoded in
the OP_RETURN in Out 0. It ensures a TSpend has not been mined before on this
chain. It ensures a TSpend has the requisite votes. It ensures a TSpend is
not overspending.
* Modify checkConnectBlock to call checkTreasuryBase and tspendChecks when
treasury agenda is active.
* Add two tables to the database. Table "treasury" records the balance as of
this block and balance changes that occurred in this block which will become
active in CoinbaseMaturity blocks. Table "tspend" records all block hashes
where a TSpend has been mined this is to detect forks and prevent a Tspend
from being mined more than once.
* Modify handleBlockchainNotification to communicate if the treasury agenda is
active and skip treasurybase transaction when needed.
* Add various Treasury parameters to chaincfg params.
* Add hardcoded Tspend signatures in dcr_tmux_simnet_setup.sh.
* Add notifytspend and stoptspend calls to the RPC server. notifytspend
notifies the mempool when a TSpend transaction arrives.
* Modify commit filters V2 to recognize TAdd and TSpend transactions. It was
possible to modify V2 instead of introducing V3 because nothing changes from
the viewpoint of the wallet and treasury opcodes are disallowed prior to
agenda activation.
* Modify AddMemPoolTransaction to skip TSpend transactions that would throw the
fee estimator off.
* Add IsTreasuryAgendaActive, OnTSpendReceived and TSpendMinedOnAncestor to
mempool.Config in order to reject/accept TSpends in the mempool.
* Modify checkPoolDoubleSpend to ignore treasurybase.
* Modify mempool.maybeAcceptTransaction to enforce treasury standardness rules.
Don't allow TSpend transactions prior to stake validation height. Skip
treasurybase and tspend transactions in the orphan test. Ensure a tspend is
in a valid window. Ensure not more than 7 TSpends are active in the mempool.
Ensure TSpend has a well-known Pi key. Ensure The provided Pi key was used to
sign the transaction. Ensure TSpend was not mined in an ancestor block.
Notify subscribers that a valid TSpend was received.
* Add standardCoinbaseOpReturn and standardTreasurybaseOpReturn to create an
OP_RETURN followed by a data push that little endian encodes the height of
the block. Then there are a number of random bytes to ensure that the
transaction hash is always random.
* Modify createCoinbaseTx to create a coinbase that is valid when treasury is
enabled or not. Additionally, alter the transaction version if treasury is
enabled.
* Add createTreasuryBaseTx that creates a standard treasurybase.
* Modify maybeInsertStakeTx to recognize treasurybase and TSpend transactions.
* Modify handleTooFewVoters to call createTreasuryBaseTx when the treasury
agenda is active. Skip copying treasurybase.
* Modify NewBlockTemplate to recognize and deal with treasury transactions.
Skip TSpend transaction if block is not a TVI. Skip TSpend transaction if it
is not in the proper window. Skip TSpend transaction if a TSpend does not
have enough yes votes. Skip TSpend transaction if it overspends the treasury
account. Skip TAdd if there are more than 20 TAdds in the block. Create
treasurybase if required. Insert valid TAdd/TSpend transactions into stake
tree.
* Add TreasuryBalance and IsTreasuryAgendaActive to rpcserver Chain interface.
* Add gettreasurybalance, sendfromtreasury and sendtotreasury calls to RPC
server.
* Add notifytspend and stopnotifytspend to RPC websocket commands.
* Add simnet miner to generate large number of blocks during rpctests without
triggering PoW difficulty increases. This is used to verify various treasury
and tspend conditions during CI/CT.
* Modify RPC voting wallet to also vote on TSpends.
* Add json tests to verify all new opcodes and corner cases in the script
engine.
* Modify isStakeOpcode to recognize treasury opcodes.
* Modify countSigOpsV0 to count TSpends.
* Modify handleStakeOutSign to deal with TSpends.
* Modify SignTxOutput to recognize TSpends.
* Add TSpendSignatureScript that signs a TSpend transaction.
* Add TreasuryAddTy and TreasurySpendTy types to the standard scripts.
* Add isTreasuryAddScript and isTreasurySpendScript functions that recognize
a form of TAdd and TSpend transactions.
* Modify ExtractPkScriptAddrs to deal with TAdd and TSpend outputs.
* Add TxVersionSeqLock = 2 and TxVersionTreasury = 3 to wire. This is
used to discriminate between treasury and non-treasury scripts.
* Rig up all functions that need the isTreasuryEnabledflag directly or
indirectly.
* Shuffle various functions around and export them when they were needed to be
called from other packages.
* Added and modified numerous tests to verify (hopefully) all corner cases that
the decentralized treasury agenda has added.
An important (and easy for implementations to miss) aspect of the
CHECKSIG opcodes is that the full signature (signature plus hash type)
that is being checked is first removed from the script prior to
calculating the signature hash against which the signature is verified.
It appears the test in the upstream btcsuite code for this was removed
during the initial Decred port instead of being converted as it should
have been.
Consequently, this converts the relevant test so it is correct for
Decred and adds it to the reference tests. Note that the first of the
two added tests is to ensure the original signature is valid prior to
testing the actual removal condition.
This removes the MINIMALDATA script verify flag from the various
reference test data since it is now a noop due to the corresponding flag
being removed from the script engine.
This removes the ScriptVerifyMinimalData flag from the txscript package,
changes the default semantics to always enforce its behavior, and
updates all callers in the repository accordingly.
This change is being made to simplify the script engine code since the
flag has always been active and required by consensus in Decred, so
there is no need to require a flag to conditionally toggle it.
It should be noted that the tests removed from script_tests.json
specifically dealt with ensuring equivalency of different ways to encode
the same numbers when the ScriptVerifyMinimalData flag is not set.
Therefore, they are no longer necessary.
A few tests which dealt with equivalency that did not already have
expected failing counterparts were converted to expected failure.
Also, several of the tests which dealt with ensuring the specific
encoding of numeric opcodes is being used have been converted to use
hashes since the minimal data requirements specifically prevent
alternate ways of pushing the same encoding which is necessary for
directly checking equality of the raw bytes.
Finally, the MINIMALDATA indicator to enable the flag in the test data
has been retained for now in order to isolate the logic changes as much
as possible.
This removes the DERSIG script verify flag from the various reference
test data since it is now a noop due to the corresponding flag being
removed from the script engine.
This removes the ScriptVerifyDERSignatures flag from the txscript
package, changes the default semantics to always enforce its behavior
and updates all callers in the repository accordingly.
This change is being made to simplify the script engine code since the
flag has always been active and required by consensus in Decred, so
there is no need to require a flag to conditionally toggle it.
It should be noted that the tests removed from script_tests.json
specifically dealt with ensuring non-DER-compliant signatures were
handled properly when the ScriptVerifyDERSignatures flag was not set.
Therefore, they are no longer necessary.
Finally, the DERSIG indicator to enable the flag in the test data has
been retained for now in order to keep the logic changes separate.
This removes the P2SH script verify flag from the various reference test
data since it is now a noop due to the corresponding flag being removed
from the script engine.
This removes the ScriptBip16 flag from the txscript package, changes the
default semantics to always enforce its behavior, and updates all
callers in the repository accordingly.
This change is being made to simplify the script engine code since the
flag has always been active and required by consensus in Decred, so there is
no need to require a flag to conditionally toggle it.
Also, since it is no longer possible to invoke the script engine without
the flag with the clean stack flag, it removes the now unused
ErrInvalidFlags error and associated tests.
It should be noted that the test removed from script_tests.json
specifically dealt with ensuring a signature script that contained
non-data-pushing opcodes was successful when neither the ScriptBip16 or
ScriptVerifySigPushOnly flags were set. Therefore, it is no longer
necessary.
Finally, the P2SH indicator to enable the flag in the test data has been
retained for now in order to keep the logic changes separate.
This updates the data driven transaction script tests to combine the
previously separate valid and invalid test data files into a single file
and adds a field for the expected result. This is a nice improvement
since it means tests can now ensure script failures are due to a
specific expected reason as opposed to only generically detecting
failure as the previous format required.
Since it is possible that the script engine might return more fine
grained errors than that test data expects, the test adapter handles
this by allowing expected errors in the test data to be mapped to
multiple txscript errors.
While performing the conversion, it also adds several tests for the
following areas:
- The test harness itself to ensure the parsing logic, particularly for
the recently added repetition syntax, is working as intended
- All of the opcodes which were converted to NOPs in Decred
to ensure they are also discouraged from use
- All of the reserved opcodes in Decred
This converts the majority of script errors from generic errors created
via errors.New and fmt.Errorf to use a concrete type that implements the
error interface with an error code and description.
This allows callers to programmatically detect the type of error via
type assertions and an error code while still allowing the errors to
provide more context.
For example, instead of just having an error the reads "disabled opcode"
as would happen prior to these changes when a disabled opcode is
encountered, the error will now read "attempt to execute disabled opcode
OP_FOO".
While it was previously possible to programmatically detect many errors
due to them being exported, they provided no additional context and
there were also various instances that were just returning errors
created on the spot which callers could not reliably detect without
resorting to looking at the actual error message, which is nearly always
bad practice.
Also, while here, export the MaxStackSize and MaxScriptSize constants
since they can be useful for consumers of the package and perform some
minor cleanup of some of the tests.
This cleans up the code for handling the checksig and checkmultisig
opcodes to explicitly call out any semantics that are likely not
obvious, correct some comments, and improve readability.
It also adds several tests to the reference script tests which exercise
the semantics of the check[multi]sig opcodes including both positive and
negative tests.
Finally, it corrects nearly all of the negative tests related to
signature checking of the script tests which were not properly updated
for the differences introduced by Decred so that they fail for the
intended reasons.
The malformed signatures in the tests were very carefully crafted to be
valid except for the very specific condition being tested. The majority
of the negative tests modified and added can be manually verified by
commenting out the relevant checks in the script engine, although a few
of them will pass because they fail for other reasons. In those cases,
prints can be added to ensure the expected failure path is being hit.
This removes the STRICTENC script verify flag from the various test data
since it is now a noop due to the corresponding flag being removed from
the script engine.
This removes the ScriptVerifyStrictEncoding flag from the txscript
package, changes the default semantics to always enforce its behavior
and updates all callers in the repository accordingly.
This change is being made to simplify the script engine code since the
flag has always been active and required by consensus in Decred, so
there is no need to require a flag to conditionally toggle it.
It should be noted that the tests removed from script_valid.json
specifically dealt with ensuring signatures not compliant with DER
encoding did not cause execution to halt early on invalid signatures
when neither of the ScriptVerifyStrictEncoding or
ScriptVerifyDERSignatures flags were set. Therefore, they are no longer
necessary.
For nearly the same reason, the tx test related to the empty pubkey
tx_valid.json was moved to tx_invalid.json. In particular, an empty
pubkey without ScriptVerifyStrictEncoding simply failed the signature
check and continued execution, while the same condition with the flag
halts execution. Thus, without the flag the final NOT in the script
would allow the script to succeed, while it does not under the strict
encoding rules.
Finally, the STRICTENC indicator to enable the flag in the test data has
been retained for now in order to keep the logic changes separate.
This removes the ScriptVerifyLowS flag from the txscript package,
changes the default semantics to always enforce its behavior and updates
all callers in the repository accordingly.
This change is being made to simplify the script engine code since the
flag has always been active and required by consensus in Decred, so
there is no need to require a flag to conditionally toggle it.
This corrects some of the script tests which were not properly updated
for the differences introduced by Decred as well as adds some additional
tests for some updated semantics.
Namely:
- Correct the redeem script hash of several tests so they fail for the
intended reason instead of due to having an invalid script hash
- Correct multisig tests to remove the dummy parameter which is not
needed by Decred
- Change the tests for previously reserved opcodes to discouraged
upgradable NOP tests to match their new semantics
- Add tests to ensure all discourage NOPs are allowed when in an
unexecuted branch
- Add tests to ensure all reserved opcodes that are not always illegal
are allowed when in an unexecuted branch
This expands upon the recently added ability to specify repeated
raw and quoted data in the test data short script form syntax to also
add syntax to allow repeated sequences of opcodes and updates several
tests to make use of it.
While here, it also corrects a few tests to actually test what they were
originally intended to test but were not updated correctly for Decred
limit changes. In particular, the following tests were corrected:
- The negative test that ensures exceeding the max opcode limit via
CHECKMULTISIG and CHECKMULTISIGVERIFY results in failure
- The positive test that ensures hitting the max opcode limit via
CHECKMULTISIG and CHECKMULTISIGVERIFY with and without keys succeeds
This improves the test data short script form syntax to allow repeated
raw and quoted data and updates several tests to make use of it.
While here, it also corrects a few tests to actually test what they were
originally intended to test but were not updated correctly for Decred
limit changes. In particular, the following tests were corrected:
- The negative test that ensures to exceeding the maximum allowed script
size results in failure
- The positive test that ensures a fully maxed out script (max script
size, max element size push, max opcodes, and max stack items)
succeeds
- The positive test that ensures OP_RESERVED does not count towards the
opcode limit
This cleans up the code for handling the mod opcode to explicitly call
out its semantics which are likely not otherwise obvious as well as
improve its readability.
It also adds several tests to the reference script tests which exercise
the semantics of the div opcode including both positive and negative
tests.
This cleans up the code for handling the div opcode to explicitly call
out its semantics which are likely not otherwise obvious as well as
improve its readability.
It also adds several tests to the reference script tests which exercise
the semantics of the div opcode including both positive and negative
tests.
This cleans up the code for handling the right shift opcode to
explicitly call out its semantics which are likely not otherwise obvious
as well as improve its readability.
It also adds several tests to the reference script tests which exercise
the semantics of the right shift opcode including both positive and
negative tests.
This cleans up the code for handling the left shift opcode to explicitly
call out its semantics which are likely not otherwise obvious as well as
improve its readability.
It also adds several tests to the reference script tests which exercise
the semantics of the left shift opcode including both positive and
negative tests.
This cleans up the code for handling the left rotation opcode to
explicitly call out its semantics which are likely not otherwise obvious
as well as improve its readability.
It also adds several tests to the reference script tests which exercise
the semantics of the left rotation opcode including both positive and
negative tests.
This cleans up the code for handling the right rotation opcode to
explicitly call out its semantics which are likely not otherwise obvious
as well as improve its readability.
It also adds several tests to the reference script tests which exercise
the semantics of the right rotation opcode including both positive and
negative tests.
This cleans up the code for handling the cat opcode to more closely
match the style used by the rest of the code and improves its test
coverage by adding several tests to the reference script tests which
exercise its semantics including both positive and negative tests.
This cleans up the code for handling the right opcode to explicitly call
out its semantics which are likely not otherwise obvious as well as
improve its readability.
It also adds several tests to the reference script tests which exercise
the semantics of the right opcode including both positive and negative
tests.
This cleans up the code for handling the left opcode to explicitly call
out its semantics which are likely not otherwise obvious as well as
improve its readability.
It also adds several tests to the reference script tests which exercise
the semantics of the left opcode including both positive and negative
tests.
This updates the recently-added JSON-based signature hash test data to
actually test the SigHashAnyOneCanPay flag in the non-fuzzer
transactions as intended.
The flag is 0x80, but the JSON test data specifies the signature hash
type in decimal, so SigHashAll|SigHashAnyOneCanPay, which is 0x81,
should've been specified as 129 decimal instead of 81 decimal. The same
applies to all combinations with the SigHashAnyOneCanPay flag.
This adds a significant number of JSON-based tests with various
transactions, scripts, and hash types, to ensure the signature hash
calculated generates the expected hash in each case.
It specifically tests some specialized transactions such as coinbase,
ticket purchase, vote, and revocation. It also includes carefully
created tests for all combinations of defined hash types along with
triggering an error due to improper use of SigHashSingle.
Finally, it also includes fuzz testing by providing a selection of 100
regular transactions with various numbers of inputs and outputs along
with randomly generated (including undefined) signature hash types and
input indexes. Due to the way that masking of the signature hash type
works, a couple of the fuzzer tests also hit the improper use of
SigHashSingle.
The test data was generated as JSON in order to make it easier for
developers of software in other languages and platforms that need to
deal with generating signature hashes to consume and prove correctness
of their implementation as well.
This modifies the script engine to replace OP_NOP3 with
OP_CHECKSEQUENCEVERIFY and adds a flag to selectively enable its
enforcement.
The new opcode examines the top item on the stack and compares it
against the sequence number of the associated transaction input in order
to allow scripts to conditionally enforce the inclusion of relative time
locks to the transaction.
The following is an overview of the changes:
- Introduce a new flag named ScriptVerifyCheckSequenceVerify to
provide conditional enforcement of the new opcode
- Introduce a constant named OP_CHECKSEQUENCEVERIFY which has the same
value as OP_NOP3 since it is replacing it
- Update opcode to name mappings accordingly
- Abstract the logic that deals with time lock verification since it is
the same for both the new opcode and OP_CHECKLOCKTIMEVERIFY
- Implement the required opcode semantics
- Add tests to ensure the opcode works as expected including when used
both correctly and incorrectly
This reverts the changes related to the CheckSequenceVerify opcode that
were merged from upstream since additional changes are needed and it's
much cleaner to implement all of code related to the sequence locks in
the same PR which will be referenced by the DCP as opposed to being
split up in multiple.
This modifies the script engine to replace OP_UNKNOWN192 with OP_SHA256
along with a flag named ScriptVerifySHA256 to selectively enable its
enforcement.
The new opcode consumes the top item from the data stack, computes its
SHA-256, and pushes the resulting digest back to the data stack.
Since it requires an item on the data stack, execution will terminate
with an error when the stack is empty. This behavior differs from
OP_UNKNOWN192 which does not consume any elements from the data stack
and therefore makes this is hard-forking change when interpreted with
the new semantics due to the ScriptVerifySHA256 flag being set. Code to
selectively enable the opcode based on the result of an agenda vote will
be added in a separate commit.
This also includes tests to ensure the opcode works as expected
including when used both correctly and incorrectly.