Add Elements-style witness serialization

This commit is contained in:
Steven Roose 2019-01-29 12:39:33 +00:00
parent 6ed8fd8ab0
commit fb72ee8fc8
50 changed files with 873 additions and 414 deletions

View file

@ -1347,9 +1347,11 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txund
// mark inputs spent
if (!tx.IsCoinBase()) {
txundo.vprevout.reserve(tx.vin.size());
for (const CTxIn &txin : tx.vin) {
for (size_t i = 0; i < tx.vin.size(); i++) {
const CTxIn& txin = tx.vin[i];
if (txin.m_is_pegin) {
std::pair<uint256, COutPoint> outpoint = std::make_pair(uint256(txin.m_pegin_witness.stack[2]), txin.prevout);
const CTxInWitness& txinwit = tx.witness.vtxinwit[i];
std::pair<uint256, COutPoint> outpoint = std::make_pair(uint256(txinwit.m_pegin_witness.stack[2]), txin.prevout);
inputs.SetPeginSpent(outpoint, true);
// Dummy undo
txundo.vprevout.emplace_back();
@ -1372,7 +1374,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight)
bool CScriptCheck::operator()() {
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
const CScriptWitness *witness = &ptxTo->vin[nIn].scriptWitness;
const CScriptWitness *witness = ptxTo->witness.vtxinwit.size() > nIn ? &ptxTo->witness.vtxinwit[nIn].scriptWitness : NULL;
return VerifyScript(scriptSig, m_tx_out.scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, m_tx_out.nValue, cacheStore, *txdata), &error);
}
@ -1450,7 +1452,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
Coin pegin_coin;
if (tx.vin[i].m_is_pegin) {
// Height of "output" in script evaluation will be 0
pegin_coin = Coin(GetPeginOutputFromWitness(tx.vin[i].m_pegin_witness), 0, false);
pegin_coin = Coin(GetPeginOutputFromWitness(tx.witness.vtxinwit[i].m_pegin_witness), 0, false);
}
const Coin& coin = tx.vin[i].m_is_pegin ? pegin_coin : inputs.AccessCoin(prevout);
@ -1677,7 +1679,7 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
}
for (unsigned int j = tx.vin.size(); j-- > 0;) {
const COutPoint &out = tx.vin[j].prevout;
const CScriptWitness& pegin_wit = tx.vin[j].m_pegin_witness;
const CScriptWitness& pegin_wit = tx.witness.vtxinwit.size() > j ? tx.witness.vtxinwit[j].m_pegin_witness : CScriptWitness();
int res = ApplyTxInUndo(std::move(txundo.vprevout[j]), view, out, tx.vin[j], pegin_wit);
if (res == DISCONNECT_FAILED) return DISCONNECT_FAILED;
fClean = fClean && res != DISCONNECT_UNCLEAN;
@ -3316,8 +3318,9 @@ void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPr
static const std::vector<unsigned char> nonce(32, 0x00);
if (commitpos != -1 && IsWitnessEnabled(pindexPrev, consensusParams) && !block.vtx[0]->HasWitness()) {
CMutableTransaction tx(*block.vtx[0]);
tx.vin[0].scriptWitness.stack.resize(1);
tx.vin[0].scriptWitness.stack[0] = nonce;
tx.witness.vtxinwit.resize(1);
tx.witness.vtxinwit[0].scriptWitness.stack.resize(1);
tx.witness.vtxinwit[0].scriptWitness.stack[0] = nonce;
block.vtx[0] = MakeTransactionRef(std::move(tx));
}
}
@ -3527,10 +3530,12 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
// The malleation check is ignored; as the transaction tree itself
// already does not permit it, it is impossible to trigger in the
// witness tree.
if (block.vtx[0]->vin[0].scriptWitness.stack.size() != 1 || block.vtx[0]->vin[0].scriptWitness.stack[0].size() != 32) {
if ((block.vtx[0]->witness.vtxinwit.empty()) ||
(block.vtx[0]->witness.vtxinwit[0].scriptWitness.stack.size() != 1) ||
(block.vtx[0]->witness.vtxinwit[0].scriptWitness.stack[0].size() != 32)) {
return state.DoS(100, false, REJECT_INVALID, "bad-witness-nonce-size", true, strprintf("%s : invalid witness reserved value size", __func__));
}
CHash256().Write(hashWitness.begin(), 32).Write(&block.vtx[0]->vin[0].scriptWitness.stack[0][0], 32).Finalize(hashWitness.begin());
CHash256().Write(hashWitness.begin(), 32).Write(&block.vtx[0]->witness.vtxinwit[0].scriptWitness.stack[0][0], 32).Finalize(hashWitness.begin());
if (memcmp(hashWitness.begin(), &block.vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
return state.DoS(100, false, REJECT_INVALID, "bad-witness-merkle-match", true, strprintf("%s : witness merkle commitment mismatch", __func__));
}