Skip to content

Commit

Permalink
Sapling CheckTransaction connection.
Browse files Browse the repository at this point in the history
  • Loading branch information
furszy committed Oct 28, 2020
1 parent 74cbe90 commit d6bcb06
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 18 deletions.
16 changes: 12 additions & 4 deletions src/consensus/tx_verify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "consensus/consensus.h"
#include "consensus/zerocoin_verify.h"
#include "sapling/sapling_validation.h"
#include "script/interpreter.h"
#include "../validation.h"

Expand Down Expand Up @@ -54,14 +55,22 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
return nSigOps;
}

bool CheckTransaction(const CTransaction& tx, bool fZerocoinActive, bool fRejectBadUTXO, CValidationState& state, bool fFakeSerialAttack, bool fColdStakingActive)
bool CheckTransaction(const CTransaction& tx, bool fZerocoinActive, bool fRejectBadUTXO, CValidationState& state, bool fFakeSerialAttack, bool fColdStakingActive, bool fSaplingActive)
{
// Basic checks that don't depend on any context
if (tx.vin.empty())
// Transactions containing empty `vin` must have non-empty `vShieldedSpend`.
if (tx.vin.empty() && (tx.sapData && tx.sapData->vShieldedSpend.empty()))
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vin-empty");
if (tx.vout.empty())
// Transactions containing empty `vout` must have non-empty `vShieldedOutput`.
if (tx.vout.empty() && (tx.sapData && tx.sapData->vShieldedOutput.empty()))
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty");

// Dispatch to Sapling validator
CAmount nValueOut = 0;
if (!SaplingValidation::CheckTransaction(tx, state, nValueOut, fSaplingActive)) {
return false;
}

// Size limits
unsigned int nMaxSize = MAX_ZEROCOIN_TX_SIZE;

Expand All @@ -70,7 +79,6 @@ bool CheckTransaction(const CTransaction& tx, bool fZerocoinActive, bool fReject

// Check for negative or overflow output values
const Consensus::Params& consensus = Params().GetConsensus();
CAmount nValueOut = 0;
for (const CTxOut& txout : tx.vout) {
if (txout.IsEmpty() && !tx.IsCoinBase() && !tx.IsCoinStake())
return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-empty");
Expand Down
2 changes: 1 addition & 1 deletion src/consensus/tx_verify.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class CValidationState;
/** Transaction validation functions */

/** Context-independent validity checks */
bool CheckTransaction(const CTransaction& tx, bool fZerocoinActive, bool fRejectBadUTXO, CValidationState& state, bool fFakeSerialAttack = false, bool fColdStakingActive=false);
bool CheckTransaction(const CTransaction& tx, bool fZerocoinActive, bool fRejectBadUTXO, CValidationState& state, bool fFakeSerialAttack = false, bool fColdStakingActive=false, bool fSaplingActive=false);

/**
* Count ECDSA signature operations the old-fashioned (pre-0.6) way
Expand Down
2 changes: 1 addition & 1 deletion src/qt/walletmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction& tran
bool fColdStakingActive = sporkManager.IsSporkActive(SPORK_17_COLDSTAKING_ENFORCEMENT);

// Double check tx before do anything
CValidationState state;
CValidationState state; // TODO: Add sapling network active flag check
if (!CheckTransaction(*transaction.getTransaction(), true, true, state, true, fColdStakingActive)) {
return TransactionCheckFailed;
}
Expand Down
9 changes: 0 additions & 9 deletions src/sapling/sapling_validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,6 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
// If the tx got to this point, must be +v2.
assert(tx.nVersion >= CTransaction::SAPLING_VERSION);

// Transactions containing empty `vin` must have non-empty `vShieldedSpend`.
if (tx.vin.empty() && tx.sapData->vShieldedSpend.empty())
return state.DoS(10, error("%s: vin empty", __func__ ),
REJECT_INVALID, "bad-txns-vin-empty");
// Transactions containing empty `vout` must have non-empty `vShieldedOutput`.
if (tx.vout.empty() && tx.sapData->vShieldedOutput.empty())
return state.DoS(10, error("%s: vout empty", __func__ ),
REJECT_INVALID, "bad-txns-vout-empty");

// Size limits
BOOST_STATIC_ASSERT(MAX_BLOCK_SIZE_CURRENT >= MAX_TX_SIZE_AFTER_SAPLING); // sanity
BOOST_STATIC_ASSERT(MAX_TX_SIZE_AFTER_SAPLING > MAX_ZEROCOIN_TX_SIZE); // sanity
Expand Down
10 changes: 7 additions & 3 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,9 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
// Check transaction
int chainHeight = chainActive.Height();
bool fColdStakingActive = sporkManager.IsSporkActive(SPORK_17_COLDSTAKING_ENFORCEMENT);
bool fSaplingActive = consensus.NetworkUpgradeActive(chainHeight, Consensus::UPGRADE_V5_DUMMY);
if (!CheckTransaction(tx, consensus.NetworkUpgradeActive(chainHeight, Consensus::UPGRADE_ZC),
true, state, isBlockBetweenFakeSerialAttackRange(chainHeight), fColdStakingActive))
true, state, isBlockBetweenFakeSerialAttackRange(chainHeight), fColdStakingActive, fSaplingActive))
return error("%s : transaction checks for %s failed with %s", __func__, tx.GetHash().ToString(), FormatStateMessage(state));

// Coinbase is only valid in a block, not as a loose transaction
Expand Down Expand Up @@ -2791,15 +2792,18 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
std::vector<CBigNum> vBlockSerials;
// TODO: Check if this is ok... blockHeight is always the tip or should we look for the prevHash and get the height?
int blockHeight = chainActive.Height() + 1;
const Consensus::Params& consensus = Params().GetConsensus();
bool fSaplingActive = consensus.NetworkUpgradeActive(blockHeight, Consensus::UPGRADE_V5_DUMMY);
for (const auto& txIn : block.vtx) {
const CTransaction& tx = *txIn;
if (!CheckTransaction(
tx,
fZerocoinActive,
blockHeight >= Params().GetConsensus().height_start_ZC_SerialRangeCheck,
blockHeight >= consensus.height_start_ZC_SerialRangeCheck,
state,
isBlockBetweenFakeSerialAttackRange(blockHeight),
fColdStakingActive
fColdStakingActive,
fSaplingActive
))
return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(),
strprintf("Transaction check failed (tx hash %s) %s", tx.GetHash().ToString(), state.GetDebugMessage()));
Expand Down

0 comments on commit d6bcb06

Please sign in to comment.