Skip to content

UTXO hasher abstraction #80

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: Development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion divi/qa/rpc-tests/BadBlockTests.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def build_bad_sig_spend (self):
amountToSend = int ((Decimal (inp["amount"]) - Decimal ('0.1')) * COIN)
tx = CTransaction ()
tx.vout.append( CTxOut(amountToSend, scriptToSendTo ) )
tx.vin.append (CTxIn (COutPoint (txid=inp["txid"], n=inp["vout"])))
tx.vin.append (CTxIn (COutPoint (txid=inp["outputhash"], n=inp["vout"])))


unsigned = tx.serialize ().hex ()
Expand Down
2 changes: 1 addition & 1 deletion divi/qa/rpc-tests/BlocksOnlyHaveSingleCoinstake.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def build_coinstake_tx (self):
tx = CTransaction ()
tx.vout.append( CTxOut(0, CScript() ) )
tx.vout.append( CTxOut(amountToSend, scriptToSendTo ) )
tx.vin.append (CTxIn (COutPoint (txid=inp["txid"], n=inp["vout"])))
tx.vin.append (CTxIn (COutPoint (txid=inp["outputhash"], n=inp["vout"])))


unsigned = tx.serialize ().hex ()
Expand Down
2 changes: 1 addition & 1 deletion divi/qa/rpc-tests/TxInputsStandardness.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def generateOutput (self, addr, amount):
tx = self.node.getrawtransaction (txid, 1)
for i in range (len (tx["vout"])):
if tx["vout"][i]["scriptPubKey"]["addresses"] == [addr]:
return (txid, i)
return (tx["txid"], i)

raise AssertionError ("failed to find destination address")

Expand Down
13 changes: 7 additions & 6 deletions divi/qa/rpc-tests/mnvaults.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Copyright (c) 2020 The DIVI developers
# Copyright (c) 2020-2021 The DIVI developers
# Distributed under the MIT/X11 software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand All @@ -26,7 +26,7 @@
class MnVaultsTest (MnTestFramework):

def __init__ (self):
super (MnVaultsTest, self).__init__ ()
super ().__init__ ()
self.base_args = ["-debug=masternode", "-debug=mocktime"]
self.cfg = None
self.number_of_nodes=7
Expand Down Expand Up @@ -94,6 +94,7 @@ def fund_vault (self):
amount = 100
txid = self.nodes[0].sendtoaddress (addr, amount)
raw = self.nodes[0].getrawtransaction (txid, 1)
outputId = raw["txid"]
vout = None
for i in range (len (raw["vout"])):
o = raw["vout"][i]
Expand All @@ -112,19 +113,19 @@ def fund_vault (self):
data = self.nodes[0].validateaddress (unvaultAddr)

tx = CTransaction ()
tx.vin.append (CTxIn (COutPoint (txid=txid, n=vout)))
tx.vin.append (CTxIn (COutPoint (txid=outputId, n=vout)))
tx.vout.append (CTxOut (amount * COIN, unhexlify (data["scriptPubKey"])))
unsigned = ToHex (tx)

validated = self.nodes[0].validateaddress (addr)
script = validated["scriptPubKey"]
prevtx = [{"txid": txid, "vout": vout, "scriptPubKey": script}]
prevtx = [{"txid": outputId, "vout": vout, "scriptPubKey": script}]
signed = self.nodes[0].signrawtransaction (unsigned, prevtx, [privkey],
"SINGLE|ANYONECANPAY")
assert_equal (signed["complete"], True)
self.unvaultTx = signed["hex"]

self.setup_masternode(2,1,"mn","copper",{"txhash":txid,"vout":vout})
self.setup_masternode(2,1,"mn","copper",{"txhash":outputId,"vout":vout})
self.cfg = self.setup[1].cfg
# FIXME: Use reward address from node 0.
self.cfg.rewardAddr = addr
Expand Down Expand Up @@ -231,7 +232,7 @@ def unvault (self):
data = self.nodes[0].validateaddress (changeAddr)

tx = FromHex (CTransaction (), self.unvaultTx)
tx.vin.append (CTxIn (COutPoint (txid=inp["txid"], n=inp["vout"])))
tx.vin.append (CTxIn (COutPoint (txid=inp["outputhash"], n=inp["vout"])))
tx.vout.append (CTxOut (change, unhexlify (data["scriptPubKey"])))
partial = ToHex (tx)

Expand Down
11 changes: 8 additions & 3 deletions divi/qa/rpc-tests/op_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ def build_op_meta_tx (self, utxos, payload, fee):
inp = None
for i in range (len (utxos)):
if utxos[i]["amount"] >= required:
inp = utxos[i]
inp = {
"txid": utxos[i]["outputhash"],
"vout": utxos[i]["vout"],
"amount": utxos[i]["amount"],
}
del utxos[i]
break
assert inp is not None, "found no suitable output"
Expand All @@ -59,8 +63,9 @@ def build_op_meta_tx (self, utxos, payload, fee):
tx = self.node.createrawtransaction ([inp], {changeAddr: change})
signed = self.node.signrawtransaction (tx)
assert_equal (signed["complete"], True)
txid = self.node.sendrawtransaction (signed["hex"])
inp["txid"] = txid
data = self.node.decoderawtransaction (signed["hex"])
self.node.sendrawtransaction (signed["hex"])
inp["txid"] = data["txid"]
inp["vout"] = 0
inp["amount"] = change

Expand Down
2 changes: 1 addition & 1 deletion divi/qa/rpc-tests/rawtransactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def find_output (self, node, value):

for u in node.listunspent ():
if u["amount"] == value:
return {"txid": u["txid"], "vout": u["vout"]}
return {"txid": u["outputhash"], "vout": u["vout"]}

raise AssertionError ("no output with value %s found" % str (value))

Expand Down
14 changes: 12 additions & 2 deletions divi/qa/rpc-tests/smartfees.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@
from util import *


def find_output(node, txid, amount):
"""
Return index to output of txid with value amount
Raises exception if there is none.
"""
txdata = node.getrawtransaction(txid, 1)
for i in range(len(txdata["vout"])):
if txdata["vout"][i]["value"] == amount:
return {"txid": txdata["txid"], "vout": i}
raise RuntimeError("find_output txid %s : %s not found"%(txid,str(amount)))

def send_zeropri_transaction(from_node, to_node, amount, fee):
"""
Create&broadcast a zero-priority transaction.
Expand All @@ -31,10 +42,9 @@ def send_zeropri_transaction(from_node, to_node, amount, fee):
self_signresult = from_node.signrawtransaction(self_rawtx)
self_txid = from_node.sendrawtransaction(self_signresult["hex"], True)

vout = find_output(from_node, self_txid, amount+fee)
# Now immediately spend the output to create a 1-input, 1-output
# zero-priority transaction:
inputs = [ { "txid" : self_txid, "vout" : vout } ]
inputs = [find_output(from_node, self_txid, amount + fee)]
outputs = { to_node.getnewaddress() : float(amount) }

rawtx = from_node.createrawtransaction(inputs, outputs)
Expand Down
6 changes: 3 additions & 3 deletions divi/qa/rpc-tests/txn_doublespend.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def create_doublespend_for_later(self,sender, node1_address):
utxos_by_account = self.collect_utxos_by_account(sender,["foo","bar"])
inputs = []
for utxo in utxos_by_account["foo"]:
inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]} )
inputs.append({ "txid" : utxo["outputhash"], "vout" : utxo["vout"]} )

outputs = {}
outputs[self.foo_address] = 9.999
Expand All @@ -65,9 +65,9 @@ def create_daisy_chain_transactions(self,sender,node1_address):
utxos_by_account = self.collect_utxos_by_account(sender,["foo","bar"])
inputs = []
for utxo in utxos_by_account["foo"]:
inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"], "address" : utxo["address"] } )
inputs.append({ "txid" : utxo["outputhash"], "vout" : utxo["vout"], "address" : utxo["address"] } )
for utxo in utxos_by_account["bar"]:
inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"], "address" : utxo["address"] } )
inputs.append({ "txid" : utxo["outputhash"], "vout" : utxo["vout"], "address" : utxo["address"] } )

outputs = {}
outputs[self.bar_address] = 29.999
Expand Down
13 changes: 1 addition & 12 deletions divi/qa/rpc-tests/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,17 +216,6 @@ def connect_nodes_bi(nodes, a, b):
connect_nodes(nodes[a], b)
connect_nodes(nodes[b], a)

def find_output(node, txid, amount):
"""
Return index to output of txid with value amount
Raises exception if there is none.
"""
txdata = node.getrawtransaction(txid, 1)
for i in range(len(txdata["vout"])):
if txdata["vout"][i]["value"] == amount:
return i
raise RuntimeError("find_output txid %s : %s not found"%(txid,str(amount)))

def gather_inputs(from_node, amount_needed, confirmations_required=1):
"""
Return a random set of unspent txouts that are enough to pay amount_needed
Expand All @@ -239,7 +228,7 @@ def gather_inputs(from_node, amount_needed, confirmations_required=1):
while total_in < amount_needed and len(utxo) > 0:
t = utxo.pop()
total_in += t["amount"]
inputs.append({ "txid" : t["txid"], "vout" : t["vout"], "address" : t["address"] } )
inputs.append({ "txid" : t["outputhash"], "vout" : t["vout"], "address" : t["address"] } )
if total_in < amount_needed:
raise RuntimeError("Insufficient funds: need %d, have %d"%(amount_needed, total_in))
return (total_in, inputs)
Expand Down
5 changes: 3 additions & 2 deletions divi/qa/rpc-tests/vaultfork.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ def fund_vault (self, owner, staker, amount):
"""

txid = owner.fundvault (staker.getnewaddress (), amount)["txhash"]
outputs = owner.getrawtransaction (txid, 1)["vout"]
data = owner.getrawtransaction (txid, 1)
outputs = data["vout"]
for n in range (len (outputs)):
if outputs[n]["scriptPubKey"]["type"] == "vault":
return {"txid": txid, "vout": n}
return {"txid": data["txid"], "vout": n}

raise AssertionError ("constructed transaction has no vault output")

Expand Down
2 changes: 1 addition & 1 deletion divi/qa/rpc-tests/wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def run_test (self):
for utxo in node0utxos:
inputs = []
outputs = {}
inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]})
inputs.append({ "txid" : utxo["outputhash"], "vout" : utxo["vout"]})
outputs[self.nodes[2].getnewaddress("from1")] = utxo["amount"]
raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
txns_to_send.append(self.nodes[0].signrawtransaction(raw_tx))
Expand Down
4 changes: 2 additions & 2 deletions divi/qa/rpc-tests/wallet_sends.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def ensure_complex_spends_resolve_balances_correctly(self,accountName=""):

sender_utxo = sender.listunspent()[0]
tx = CTransaction ()
tx.vin.append (CTxIn (COutPoint (txid=sender_utxo["txid"], n=sender_utxo["vout"])))
tx.vin.append (CTxIn (COutPoint (txid=sender_utxo["outputhash"], n=sender_utxo["vout"])))
tx.vin.append (CTxIn (COutPoint (txid=receiver_utxo[0], n=receiver_utxo[1])))
tx.vin.append (CTxIn (COutPoint (txid=multisigTxID, n=multisigOutputIndex)))

Expand Down Expand Up @@ -154,7 +154,7 @@ def join_sends_compute_balance_correctly(self):

sender_utxo = sender.listunspent()[0]
tx = CTransaction ()
tx.vin.append (CTxIn (COutPoint (txid=sender_utxo["txid"], n=sender_utxo["vout"])))
tx.vin.append (CTxIn (COutPoint (txid=sender_utxo["outputhash"], n=sender_utxo["vout"])))
tx.vin.append (CTxIn (COutPoint (txid=receiver_utxo[0], n=receiver_utxo[1])))

amountToSend = int ((Decimal (2500.0) - Decimal ('0.1')) * COIN)
Expand Down
4 changes: 3 additions & 1 deletion divi/src/ActiveChainManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,14 @@ bool ActiveChainManager::DisconnectBlock(
return error("DisconnectBlock() : block and undo data inconsistent");
}

const BlockUtxoHasher utxoHasher;

bool fClean = true;
IndexDatabaseUpdates indexDBUpdates;
// undo transactions in reverse order
for (int transactionIndex = block.vtx.size() - 1; transactionIndex >= 0; transactionIndex--) {
const CTransaction& tx = block.vtx[transactionIndex];
const TransactionLocationReference txLocationReference(tx, pindex->nHeight, transactionIndex);
const TransactionLocationReference txLocationReference(utxoHasher, tx, pindex->nHeight, transactionIndex);
const auto* undo = (transactionIndex > 0 ? &blockUndo.vtxundo[transactionIndex - 1] : nullptr);
const TxReversalStatus status = UpdateCoinsReversingTransaction(tx, txLocationReference, view, undo);
if(!CheckTxReversalStatus(status,fClean))
Expand Down
9 changes: 5 additions & 4 deletions divi/src/BlockMemoryPoolTransactionCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <defaultValues.h>
#include <Logging.h>
#include <TransactionOpCounting.h>
#include <OutputHash.h>
#include <UtxoCheckingAndUpdating.h>

#include <Settings.h>
Expand Down Expand Up @@ -52,7 +53,7 @@ class COrphan
{
public:
const CTransaction* ptx;
std::set<uint256> setDependsOn;
std::set<OutputHash> setDependsOn;
CFeeRate feeRate;
double coinAgeOfInputsPerByte;

Expand Down Expand Up @@ -144,7 +145,7 @@ void BlockMemoryPoolTransactionCollector::ComputeTransactionPriority(

void BlockMemoryPoolTransactionCollector::AddDependingTransactionsToPriorityQueue(
DependingTransactionsMap& dependentTransactions,
const uint256& hash,
const OutputHash& hash,
std::vector<TxPriority>& vecPriority,
TxPriorityCompare& comparer) const
{
Expand Down Expand Up @@ -324,10 +325,10 @@ std::vector<PrioritizedTransactionData> BlockMemoryPoolTransactionCollector::Pri
currentBlockSigOps += transactionSigOpCount;

CTxUndo txundo;
UpdateCoinsWithTransaction(tx, view, txundo, nHeight);
UpdateCoinsWithTransaction(tx, view, txundo, mempool_.GetUtxoHasher(), nHeight);

// Add transactions that depend on this one to the priority queue
AddDependingTransactionsToPriorityQueue(dependentTransactions, hash, vecPriority, comparer);
AddDependingTransactionsToPriorityQueue(dependentTransactions, mempool_.GetUtxoHasher().GetUtxoHash(tx), vecPriority, comparer);
}

LogPrintf("%s: total size %u\n",__func__, currentBlockSize);
Expand Down
5 changes: 3 additions & 2 deletions divi/src/BlockMemoryPoolTransactionCollector.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class CTxMemPool;
class CBlockTemplate;
class CBlockHeader;
class CFeeRate;
class OutputHash;
class Settings;

struct PrioritizedTransactionData
Expand All @@ -52,7 +53,7 @@ class CChain;
class BlockMemoryPoolTransactionCollector: public I_BlockTransactionCollector
{
private:
using DependingTransactionsMap = std::map<uint256, std::vector<std::shared_ptr<COrphan>>>;
using DependingTransactionsMap = std::map<OutputHash, std::vector<std::shared_ptr<COrphan>>>;

CCoinsViewCache* baseCoinsViewCache_;
const CChain& activeChain_;
Expand All @@ -78,7 +79,7 @@ class BlockMemoryPoolTransactionCollector: public I_BlockTransactionCollector
std::vector<TxPriority>& vecPriority) const;
void AddDependingTransactionsToPriorityQueue(
DependingTransactionsMap& mapDependers,
const uint256& hash,
const OutputHash& hash,
std::vector<TxPriority>& vecPriority,
TxPriorityCompare& comparer) const;

Expand Down
6 changes: 4 additions & 2 deletions divi/src/BlockTransactionChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ void TransactionLocationRecorder::RecordTxLocationData(

BlockTransactionChecker::BlockTransactionChecker(
const CBlock& block,
const TransactionUtxoHasher& utxoHasher,
CValidationState& state,
CBlockIndex* pindex,
CCoinsViewCache& view,
Expand All @@ -48,6 +49,7 @@ BlockTransactionChecker::BlockTransactionChecker(
): blockundo_(block.vtx.size() - 1)
, block_(block)
, activation_(pindex)
, utxoHasher_(utxoHasher)
, state_(state)
, pindex_(pindex)
, view_(view)
Expand Down Expand Up @@ -122,7 +124,7 @@ bool BlockTransactionChecker::Check(const CBlockRewards& nExpectedMint,bool fJus

for (unsigned int i = 0; i < block_.vtx.size(); i++) {
const CTransaction& tx = block_.vtx[i];
const TransactionLocationReference txLocationRef(tx, pindex_->nHeight, i);
const TransactionLocationReference txLocationRef(utxoHasher_, tx, pindex_->nHeight, i);

if(!txInputChecker_.InputsAreValid(tx))
{
Expand All @@ -147,7 +149,7 @@ bool BlockTransactionChecker::Check(const CBlockRewards& nExpectedMint,bool fJus
}

IndexDatabaseUpdateCollector::RecordTransaction(tx,txLocationRef,view_, indexDatabaseUpdates);
UpdateCoinsWithTransaction(tx, view_, blockundo_.vtxundo[i>0u? i-1: 0u], pindex_->nHeight);
UpdateCoinsWithTransaction(tx, view_, blockundo_.vtxundo[i>0u? i-1: 0u], utxoHasher_, pindex_->nHeight);
txLocationRecorder_.RecordTxLocationData(tx,indexDatabaseUpdates.txLocationData);
}
return true;
Expand Down
3 changes: 3 additions & 0 deletions divi/src/BlockTransactionChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class CBlock;
class CValidationState;
class CCoinsViewCache;
class CBlockRewards;
class TransactionUtxoHasher;

class TransactionLocationRecorder
{
Expand All @@ -38,6 +39,7 @@ class BlockTransactionChecker
CBlockUndo blockundo_;
const CBlock& block_;
const ActivationState activation_;
const TransactionUtxoHasher& utxoHasher_;
CValidationState& state_;
CBlockIndex* pindex_;
CCoinsViewCache& view_;
Expand All @@ -58,6 +60,7 @@ class BlockTransactionChecker

BlockTransactionChecker(
const CBlock& block,
const TransactionUtxoHasher& utxoHasher,
CValidationState& state,
CBlockIndex* pindex,
CCoinsViewCache& view,
Expand Down
Loading