Auto merge of #1090 - ebfull:rename-pour-and-serial, r=ebfull

Rename things to match protocol specification

This is a pass through the code to eliminate usage of "pour" and "serial" and any other outdated terminology.

Closes #602
This commit is contained in:
zkbot 2016-07-18 19:58:25 +00:00
commit 4d459f93a4
26 changed files with 512 additions and 512 deletions

View File

@ -27,8 +27,8 @@ testScripts=(
'merkle_blocks.py' 'merkle_blocks.py'
'signrawtransactions.py' 'signrawtransactions.py'
'walletbackup.py' 'walletbackup.py'
'zcpour.py' 'zcjoinsplit.py'
'zcpourdoublespend.py' 'zcjoinsplitdoublespend.py'
); );
testScriptsExt=( testScriptsExt=(
'bipdersig-p2p.py' 'bipdersig-p2p.py'

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python2 #!/usr/bin/env python2
# #
# Test Pour semantics # Test joinsplit semantics
# #
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
@ -11,7 +11,7 @@ import os
import shutil import shutil
import sys import sys
class PourTxTest(BitcoinTestFramework): class JoinSplitTest(BitcoinTestFramework):
def setup_network(self): def setup_network(self):
self.nodes = [] self.nodes = []
self.is_network_split = False self.is_network_split = False
@ -24,27 +24,27 @@ class PourTxTest(BitcoinTestFramework):
(total_in, inputs) = gather_inputs(self.nodes[0], 40) (total_in, inputs) = gather_inputs(self.nodes[0], 40)
protect_tx = self.nodes[0].createrawtransaction(inputs, {}) protect_tx = self.nodes[0].createrawtransaction(inputs, {})
pour_result = self.nodes[0].zcrawpour(protect_tx, {}, {zcaddress:39.9}, 39.9, 0) joinsplit_result = self.nodes[0].zcrawjoinsplit(protect_tx, {}, {zcaddress:39.9}, 39.9, 0)
receive_result = self.nodes[0].zcrawreceive(zcsecretkey, pour_result["encryptedbucket1"]) receive_result = self.nodes[0].zcrawreceive(zcsecretkey, joinsplit_result["encryptednote1"])
assert_equal(receive_result["exists"], False) assert_equal(receive_result["exists"], False)
protect_tx = self.nodes[0].signrawtransaction(pour_result["rawtxn"]) protect_tx = self.nodes[0].signrawtransaction(joinsplit_result["rawtxn"])
self.nodes[0].sendrawtransaction(protect_tx["hex"]) self.nodes[0].sendrawtransaction(protect_tx["hex"])
self.nodes[0].generate(1) self.nodes[0].generate(1)
receive_result = self.nodes[0].zcrawreceive(zcsecretkey, pour_result["encryptedbucket1"]) receive_result = self.nodes[0].zcrawreceive(zcsecretkey, joinsplit_result["encryptednote1"])
assert_equal(receive_result["exists"], True) assert_equal(receive_result["exists"], True)
pour_tx = self.nodes[0].createrawtransaction([], {}) joinsplit_tx = self.nodes[0].createrawtransaction([], {})
pour_result = self.nodes[0].zcrawpour(pour_tx, {receive_result["bucket"] : zcsecretkey}, {zcaddress: 39.8}, 0, 0.1) joinsplit_result = self.nodes[0].zcrawjoinsplit(joinsplit_tx, {receive_result["note"] : zcsecretkey}, {zcaddress: 39.8}, 0, 0.1)
self.nodes[0].sendrawtransaction(pour_result["rawtxn"]) self.nodes[0].sendrawtransaction(joinsplit_result["rawtxn"])
self.nodes[0].generate(1) self.nodes[0].generate(1)
print "Done!" print "Done!"
receive_result = self.nodes[0].zcrawreceive(zcsecretkey, pour_result["encryptedbucket1"]) receive_result = self.nodes[0].zcrawreceive(zcsecretkey, joinsplit_result["encryptednote1"])
assert_equal(receive_result["exists"], True) assert_equal(receive_result["exists"], True)
if __name__ == '__main__': if __name__ == '__main__':
PourTxTest().main() JoinSplitTest().main()

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python2 #!/usr/bin/env python2
# #
# Tests a Pour double-spend and a subsequent reorg. # Tests a joinsplit double-spend and a subsequent reorg.
# #
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
@ -12,10 +12,10 @@ import shutil
import sys import sys
import time import time
class PourTxTest(BitcoinTestFramework): class JoinSplitTest(BitcoinTestFramework):
def setup_network(self): def setup_network(self):
# Start with split network: # Start with split network:
return super(PourTxTest, self).setup_network(True) return super(JoinSplitTest, self).setup_network(True)
def txid_in_mempool(self, node, txid): def txid_in_mempool(self, node, txid):
exception_triggered = False exception_triggered = False
@ -27,7 +27,7 @@ class PourTxTest(BitcoinTestFramework):
return not exception_triggered return not exception_triggered
def cannot_pour(self, node, txn): def cannot_joinsplit(self, node, txn):
exception_triggered = False exception_triggered = False
try: try:
@ -37,8 +37,8 @@ class PourTxTest(BitcoinTestFramework):
return exception_triggered return exception_triggered
def expect_cannot_pour(self, node, txn): def expect_cannot_joinsplit(self, node, txn):
assert_equal(self.cannot_pour(node, txn), True) assert_equal(self.cannot_joinsplit(node, txn), True)
def run_test(self): def run_test(self):
# All nodes should start with 250 BTC: # All nodes should start with 250 BTC:
@ -56,7 +56,7 @@ class PourTxTest(BitcoinTestFramework):
for i in range(4): for i in range(4):
(total_in, inputs) = gather_inputs(self.nodes[i], 40) (total_in, inputs) = gather_inputs(self.nodes[i], 40)
pool[i] = self.nodes[i].createrawtransaction(inputs, {}) pool[i] = self.nodes[i].createrawtransaction(inputs, {})
pool[i] = self.nodes[i].zcrawpour(pool[i], {}, {zcaddress:39.9}, 39.9, 0) pool[i] = self.nodes[i].zcrawjoinsplit(pool[i], {}, {zcaddress:39.9}, 39.9, 0)
signed = self.nodes[i].signrawtransaction(pool[i]["rawtxn"]) signed = self.nodes[i].signrawtransaction(pool[i]["rawtxn"])
# send the tx to both halves of the network # send the tx to both halves of the network
@ -64,54 +64,54 @@ class PourTxTest(BitcoinTestFramework):
self.nodes[0].generate(1) self.nodes[0].generate(1)
self.nodes[2].sendrawtransaction(signed["hex"]) self.nodes[2].sendrawtransaction(signed["hex"])
self.nodes[2].generate(1) self.nodes[2].generate(1)
pool[i] = pool[i]["encryptedbucket1"] pool[i] = pool[i]["encryptednote1"]
sync_blocks(self.nodes[0:2]) sync_blocks(self.nodes[0:2])
sync_blocks(self.nodes[2:4]) sync_blocks(self.nodes[2:4])
# Confirm that the protects have taken place # Confirm that the protects have taken place
for i in range(4): for i in range(4):
enc_bucket = pool[i] enc_note = pool[i]
receive_result = self.nodes[0].zcrawreceive(zcsecretkey, enc_bucket) receive_result = self.nodes[0].zcrawreceive(zcsecretkey, enc_note)
assert_equal(receive_result["exists"], True) assert_equal(receive_result["exists"], True)
pool[i] = receive_result["bucket"] pool[i] = receive_result["note"]
# Extra confirmations # Extra confirmations
receive_result = self.nodes[1].zcrawreceive(zcsecretkey, enc_bucket) receive_result = self.nodes[1].zcrawreceive(zcsecretkey, enc_note)
assert_equal(receive_result["exists"], True) assert_equal(receive_result["exists"], True)
receive_result = self.nodes[2].zcrawreceive(zcsecretkey, enc_bucket) receive_result = self.nodes[2].zcrawreceive(zcsecretkey, enc_note)
assert_equal(receive_result["exists"], True) assert_equal(receive_result["exists"], True)
receive_result = self.nodes[3].zcrawreceive(zcsecretkey, enc_bucket) receive_result = self.nodes[3].zcrawreceive(zcsecretkey, enc_note)
assert_equal(receive_result["exists"], True) assert_equal(receive_result["exists"], True)
blank_tx = self.nodes[0].createrawtransaction([], {}) blank_tx = self.nodes[0].createrawtransaction([], {})
# Create pour {A, B}->{*} # Create joinsplit {A, B}->{*}
pour_AB = self.nodes[0].zcrawpour(blank_tx, joinsplit_AB = self.nodes[0].zcrawjoinsplit(blank_tx,
{pool[0] : zcsecretkey, pool[1] : zcsecretkey}, {pool[0] : zcsecretkey, pool[1] : zcsecretkey},
{zcaddress:(39.9*2)-0.1}, {zcaddress:(39.9*2)-0.1},
0, 0.1) 0, 0.1)
# Create pour {B, C}->{*} # Create joinsplit {B, C}->{*}
pour_BC = self.nodes[0].zcrawpour(blank_tx, joinsplit_BC = self.nodes[0].zcrawjoinsplit(blank_tx,
{pool[1] : zcsecretkey, pool[2] : zcsecretkey}, {pool[1] : zcsecretkey, pool[2] : zcsecretkey},
{zcaddress:(39.9*2)-0.1}, {zcaddress:(39.9*2)-0.1},
0, 0.1) 0, 0.1)
# Create pour {C, D}->{*} # Create joinsplit {C, D}->{*}
pour_CD = self.nodes[0].zcrawpour(blank_tx, joinsplit_CD = self.nodes[0].zcrawjoinsplit(blank_tx,
{pool[2] : zcsecretkey, pool[3] : zcsecretkey}, {pool[2] : zcsecretkey, pool[3] : zcsecretkey},
{zcaddress:(39.9*2)-0.1}, {zcaddress:(39.9*2)-0.1},
0, 0.1) 0, 0.1)
# Create pour {A, D}->{*} # Create joinsplit {A, D}->{*}
pour_AD = self.nodes[0].zcrawpour(blank_tx, joinsplit_AD = self.nodes[0].zcrawjoinsplit(blank_tx,
{pool[0] : zcsecretkey, pool[3] : zcsecretkey}, {pool[0] : zcsecretkey, pool[3] : zcsecretkey},
{zcaddress:(39.9*2)-0.1}, {zcaddress:(39.9*2)-0.1},
0, 0.1) 0, 0.1)
# (a) Node 0 will spend pour AB, then attempt to # (a) Node 0 will spend joinsplit AB, then attempt to
# double-spend it with BC. It should fail before and # double-spend it with BC. It should fail before and
# after Node 0 mines blocks. # after Node 0 mines blocks.
# #
@ -126,9 +126,9 @@ class PourTxTest(BitcoinTestFramework):
# (a) # (a)
AB_txid = self.nodes[0].sendrawtransaction(pour_AB["rawtxn"]) AB_txid = self.nodes[0].sendrawtransaction(joinsplit_AB["rawtxn"])
self.expect_cannot_pour(self.nodes[0], pour_BC["rawtxn"]) self.expect_cannot_joinsplit(self.nodes[0], joinsplit_BC["rawtxn"])
# Wait until node[1] receives AB before we attempt to double-spend # Wait until node[1] receives AB before we attempt to double-spend
# with BC. # with BC.
@ -139,17 +139,17 @@ class PourTxTest(BitcoinTestFramework):
time.sleep(0.2) time.sleep(0.2)
print "Done!\n" print "Done!\n"
self.expect_cannot_pour(self.nodes[1], pour_BC["rawtxn"]) self.expect_cannot_joinsplit(self.nodes[1], joinsplit_BC["rawtxn"])
# Generate a block # Generate a block
self.nodes[0].generate(1) self.nodes[0].generate(1)
sync_blocks(self.nodes[0:2]) sync_blocks(self.nodes[0:2])
self.expect_cannot_pour(self.nodes[0], pour_BC["rawtxn"]) self.expect_cannot_joinsplit(self.nodes[0], joinsplit_BC["rawtxn"])
self.expect_cannot_pour(self.nodes[1], pour_BC["rawtxn"]) self.expect_cannot_joinsplit(self.nodes[1], joinsplit_BC["rawtxn"])
# (b) # (b)
self.nodes[2].sendrawtransaction(pour_BC["rawtxn"]) self.nodes[2].sendrawtransaction(joinsplit_BC["rawtxn"])
self.nodes[2].generate(5) self.nodes[2].generate(5)
# Connect the two nodes # Connect the two nodes
@ -158,26 +158,26 @@ class PourTxTest(BitcoinTestFramework):
sync_blocks(self.nodes) sync_blocks(self.nodes)
# AB and CD should all be impossible to spend for each node. # AB and CD should all be impossible to spend for each node.
self.expect_cannot_pour(self.nodes[0], pour_AB["rawtxn"]) self.expect_cannot_joinsplit(self.nodes[0], joinsplit_AB["rawtxn"])
self.expect_cannot_pour(self.nodes[0], pour_CD["rawtxn"]) self.expect_cannot_joinsplit(self.nodes[0], joinsplit_CD["rawtxn"])
self.expect_cannot_pour(self.nodes[1], pour_AB["rawtxn"]) self.expect_cannot_joinsplit(self.nodes[1], joinsplit_AB["rawtxn"])
self.expect_cannot_pour(self.nodes[1], pour_CD["rawtxn"]) self.expect_cannot_joinsplit(self.nodes[1], joinsplit_CD["rawtxn"])
self.expect_cannot_pour(self.nodes[2], pour_AB["rawtxn"]) self.expect_cannot_joinsplit(self.nodes[2], joinsplit_AB["rawtxn"])
self.expect_cannot_pour(self.nodes[2], pour_CD["rawtxn"]) self.expect_cannot_joinsplit(self.nodes[2], joinsplit_CD["rawtxn"])
self.expect_cannot_pour(self.nodes[3], pour_AB["rawtxn"]) self.expect_cannot_joinsplit(self.nodes[3], joinsplit_AB["rawtxn"])
self.expect_cannot_pour(self.nodes[3], pour_CD["rawtxn"]) self.expect_cannot_joinsplit(self.nodes[3], joinsplit_CD["rawtxn"])
# (c) # (c)
# AD should be possible to send due to the reorg that # AD should be possible to send due to the reorg that
# tossed out AB. # tossed out AB.
self.nodes[0].sendrawtransaction(pour_AD["rawtxn"]) self.nodes[0].sendrawtransaction(joinsplit_AD["rawtxn"])
self.nodes[0].generate(1) self.nodes[0].generate(1)
sync_blocks(self.nodes) sync_blocks(self.nodes)
if __name__ == '__main__': if __name__ == '__main__':
PourTxTest().main() JoinSplitTest().main()

View File

@ -41,7 +41,7 @@ bool CCoins::Spend(uint32_t nPos)
return true; return true;
} }
bool CCoinsView::GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const { return false; } bool CCoinsView::GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const { return false; }
bool CCoinsView::GetSerial(const uint256 &serial) const { return false; } bool CCoinsView::GetNullifier(const uint256 &nullifier) const { return false; }
bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; } bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; }
bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; } bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; }
uint256 CCoinsView::GetBestBlock() const { return uint256(); } uint256 CCoinsView::GetBestBlock() const { return uint256(); }
@ -50,14 +50,14 @@ bool CCoinsView::BatchWrite(CCoinsMap &mapCoins,
const uint256 &hashBlock, const uint256 &hashBlock,
const uint256 &hashAnchor, const uint256 &hashAnchor,
CAnchorsMap &mapAnchors, CAnchorsMap &mapAnchors,
CSerialsMap &mapSerials) { return false; } CNullifiersMap &mapNullifiers) { return false; }
bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; } bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; }
CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { } CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { }
bool CCoinsViewBacked::GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const { return base->GetAnchorAt(rt, tree); } bool CCoinsViewBacked::GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const { return base->GetAnchorAt(rt, tree); }
bool CCoinsViewBacked::GetSerial(const uint256 &serial) const { return base->GetSerial(serial); } bool CCoinsViewBacked::GetNullifier(const uint256 &nullifier) const { return base->GetNullifier(nullifier); }
bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); } bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); }
bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); } bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); }
uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); } uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
@ -67,7 +67,7 @@ bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins,
const uint256 &hashBlock, const uint256 &hashBlock,
const uint256 &hashAnchor, const uint256 &hashAnchor,
CAnchorsMap &mapAnchors, CAnchorsMap &mapAnchors,
CSerialsMap &mapSerials) { return base->BatchWrite(mapCoins, hashBlock, hashAnchor, mapAnchors, mapSerials); } CNullifiersMap &mapNullifiers) { return base->BatchWrite(mapCoins, hashBlock, hashAnchor, mapAnchors, mapNullifiers); }
bool CCoinsViewBacked::GetStats(CCoinsStats &stats) const { return base->GetStats(stats); } bool CCoinsViewBacked::GetStats(CCoinsStats &stats) const { return base->GetStats(stats); }
CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {} CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {}
@ -82,7 +82,7 @@ CCoinsViewCache::~CCoinsViewCache()
size_t CCoinsViewCache::DynamicMemoryUsage() const { size_t CCoinsViewCache::DynamicMemoryUsage() const {
return memusage::DynamicUsage(cacheCoins) + return memusage::DynamicUsage(cacheCoins) +
memusage::DynamicUsage(cacheAnchors) + memusage::DynamicUsage(cacheAnchors) +
memusage::DynamicUsage(cacheSerials) + memusage::DynamicUsage(cacheNullifiers) +
cachedCoinsUsage; cachedCoinsUsage;
} }
@ -128,16 +128,16 @@ bool CCoinsViewCache::GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tr
return true; return true;
} }
bool CCoinsViewCache::GetSerial(const uint256 &serial) const { bool CCoinsViewCache::GetNullifier(const uint256 &nullifier) const {
CSerialsMap::iterator it = cacheSerials.find(serial); CNullifiersMap::iterator it = cacheNullifiers.find(nullifier);
if (it != cacheSerials.end()) if (it != cacheNullifiers.end())
return it->second.entered; return it->second.entered;
CSerialsCacheEntry entry; CNullifiersCacheEntry entry;
bool tmp = base->GetSerial(serial); bool tmp = base->GetNullifier(nullifier);
entry.entered = tmp; entry.entered = tmp;
cacheSerials.insert(std::make_pair(serial, entry)); cacheNullifiers.insert(std::make_pair(nullifier, entry));
return tmp; return tmp;
} }
@ -149,7 +149,7 @@ void CCoinsViewCache::PushAnchor(const ZCIncrementalMerkleTree &tree) {
// We don't want to overwrite an anchor we already have. // We don't want to overwrite an anchor we already have.
// This occurs when a block doesn't modify mapAnchors at all, // This occurs when a block doesn't modify mapAnchors at all,
// because there are no pours. We could get around this a // because there are no joinsplits. We could get around this a
// different way (make all blocks modify mapAnchors somehow) // different way (make all blocks modify mapAnchors somehow)
// but this is simpler to reason about. // but this is simpler to reason about.
if (currentRoot != newrt) { if (currentRoot != newrt) {
@ -185,10 +185,10 @@ void CCoinsViewCache::PopAnchor(const uint256 &newrt) {
} }
} }
void CCoinsViewCache::SetSerial(const uint256 &serial, bool spent) { void CCoinsViewCache::SetNullifier(const uint256 &nullifier, bool spent) {
std::pair<CSerialsMap::iterator, bool> ret = cacheSerials.insert(std::make_pair(serial, CSerialsCacheEntry())); std::pair<CNullifiersMap::iterator, bool> ret = cacheNullifiers.insert(std::make_pair(nullifier, CNullifiersCacheEntry()));
ret.first->second.entered = spent; ret.first->second.entered = spent;
ret.first->second.flags |= CSerialsCacheEntry::DIRTY; ret.first->second.flags |= CNullifiersCacheEntry::DIRTY;
} }
bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) const { bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) const {
@ -260,7 +260,7 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins,
const uint256 &hashBlockIn, const uint256 &hashBlockIn,
const uint256 &hashAnchorIn, const uint256 &hashAnchorIn,
CAnchorsMap &mapAnchors, CAnchorsMap &mapAnchors,
CSerialsMap &mapSerials) { CNullifiersMap &mapNullifiers) {
assert(!hasModifier); assert(!hasModifier);
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) { for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization). if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
@ -326,29 +326,29 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins,
mapAnchors.erase(itOld); mapAnchors.erase(itOld);
} }
for (CSerialsMap::iterator child_it = mapSerials.begin(); child_it != mapSerials.end();) for (CNullifiersMap::iterator child_it = mapNullifiers.begin(); child_it != mapNullifiers.end();)
{ {
if (child_it->second.flags & CSerialsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization). if (child_it->second.flags & CNullifiersCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
CSerialsMap::iterator parent_it = cacheSerials.find(child_it->first); CNullifiersMap::iterator parent_it = cacheNullifiers.find(child_it->first);
if (parent_it == cacheSerials.end()) { if (parent_it == cacheNullifiers.end()) {
if (child_it->second.entered) { if (child_it->second.entered) {
// Parent doesn't have an entry, but child has a SPENT serial. // Parent doesn't have an entry, but child has a SPENT nullifier.
// Move the spent serial up. // Move the spent nullifier up.
CSerialsCacheEntry& entry = cacheSerials[child_it->first]; CNullifiersCacheEntry& entry = cacheNullifiers[child_it->first];
entry.entered = true; entry.entered = true;
entry.flags = CSerialsCacheEntry::DIRTY; entry.flags = CNullifiersCacheEntry::DIRTY;
} }
} else { } else {
if (parent_it->second.entered != child_it->second.entered) { if (parent_it->second.entered != child_it->second.entered) {
parent_it->second.entered = child_it->second.entered; parent_it->second.entered = child_it->second.entered;
parent_it->second.flags |= CSerialsCacheEntry::DIRTY; parent_it->second.flags |= CNullifiersCacheEntry::DIRTY;
} }
} }
} }
CSerialsMap::iterator itOld = child_it++; CNullifiersMap::iterator itOld = child_it++;
mapSerials.erase(itOld); mapNullifiers.erase(itOld);
} }
hashAnchor = hashAnchorIn; hashAnchor = hashAnchorIn;
@ -357,10 +357,10 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins,
} }
bool CCoinsViewCache::Flush() { bool CCoinsViewCache::Flush() {
bool fOk = base->BatchWrite(cacheCoins, hashBlock, hashAnchor, cacheAnchors, cacheSerials); bool fOk = base->BatchWrite(cacheCoins, hashBlock, hashAnchor, cacheAnchors, cacheNullifiers);
cacheCoins.clear(); cacheCoins.clear();
cacheAnchors.clear(); cacheAnchors.clear();
cacheSerials.clear(); cacheNullifiers.clear();
cachedCoinsUsage = 0; cachedCoinsUsage = 0;
return fOk; return fOk;
} }
@ -385,35 +385,35 @@ CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const
for (unsigned int i = 0; i < tx.vin.size(); i++) for (unsigned int i = 0; i < tx.vin.size(); i++)
nResult += GetOutputFor(tx.vin[i]).nValue; nResult += GetOutputFor(tx.vin[i]).nValue;
nResult += tx.GetPourValueIn(); nResult += tx.GetJoinSplitValueIn();
return nResult; return nResult;
} }
bool CCoinsViewCache::HavePourRequirements(const CTransaction& tx) const bool CCoinsViewCache::HaveJoinSplitRequirements(const CTransaction& tx) const
{ {
boost::unordered_map<uint256, ZCIncrementalMerkleTree, CCoinsKeyHasher> intermediates; boost::unordered_map<uint256, ZCIncrementalMerkleTree, CCoinsKeyHasher> intermediates;
BOOST_FOREACH(const CPourTx &pour, tx.vpour) BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit)
{ {
BOOST_FOREACH(const uint256& serial, pour.serials) BOOST_FOREACH(const uint256& nullifier, joinsplit.nullifiers)
{ {
if (GetSerial(serial)) { if (GetNullifier(nullifier)) {
// If the serial is set, this transaction // If the nullifier is set, this transaction
// double-spends! // double-spends!
return false; return false;
} }
} }
ZCIncrementalMerkleTree tree; ZCIncrementalMerkleTree tree;
auto it = intermediates.find(pour.anchor); auto it = intermediates.find(joinsplit.anchor);
if (it != intermediates.end()) { if (it != intermediates.end()) {
tree = it->second; tree = it->second;
} else if (!GetAnchorAt(pour.anchor, tree)) { } else if (!GetAnchorAt(joinsplit.anchor, tree)) {
return false; return false;
} }
BOOST_FOREACH(const uint256& commitment, pour.commitments) BOOST_FOREACH(const uint256& commitment, joinsplit.commitments)
{ {
tree.append(commitment); tree.append(commitment);
} }

View File

@ -309,21 +309,21 @@ struct CAnchorsCacheEntry
CAnchorsCacheEntry() : entered(false), flags(0) {} CAnchorsCacheEntry() : entered(false), flags(0) {}
}; };
struct CSerialsCacheEntry struct CNullifiersCacheEntry
{ {
bool entered; // If the serial is spent or not bool entered; // If the nullifier is spent or not
unsigned char flags; unsigned char flags;
enum Flags { enum Flags {
DIRTY = (1 << 0), // This cache entry is potentially different from the version in the parent view. DIRTY = (1 << 0), // This cache entry is potentially different from the version in the parent view.
}; };
CSerialsCacheEntry() : entered(false), flags(0) {} CNullifiersCacheEntry() : entered(false), flags(0) {}
}; };
typedef boost::unordered_map<uint256, CCoinsCacheEntry, CCoinsKeyHasher> CCoinsMap; typedef boost::unordered_map<uint256, CCoinsCacheEntry, CCoinsKeyHasher> CCoinsMap;
typedef boost::unordered_map<uint256, CAnchorsCacheEntry, CCoinsKeyHasher> CAnchorsMap; typedef boost::unordered_map<uint256, CAnchorsCacheEntry, CCoinsKeyHasher> CAnchorsMap;
typedef boost::unordered_map<uint256, CSerialsCacheEntry, CCoinsKeyHasher> CSerialsMap; typedef boost::unordered_map<uint256, CNullifiersCacheEntry, CCoinsKeyHasher> CNullifiersMap;
struct CCoinsStats struct CCoinsStats
{ {
@ -346,8 +346,8 @@ public:
//! Retrieve the tree at a particular anchored root in the chain //! Retrieve the tree at a particular anchored root in the chain
virtual bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const; virtual bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const;
//! Determine whether a serial is spent or not //! Determine whether a nullifier is spent or not
virtual bool GetSerial(const uint256 &serial) const; virtual bool GetNullifier(const uint256 &nullifier) const;
//! Retrieve the CCoins (unspent transaction outputs) for a given txid //! Retrieve the CCoins (unspent transaction outputs) for a given txid
virtual bool GetCoins(const uint256 &txid, CCoins &coins) const; virtual bool GetCoins(const uint256 &txid, CCoins &coins) const;
@ -368,7 +368,7 @@ public:
const uint256 &hashBlock, const uint256 &hashBlock,
const uint256 &hashAnchor, const uint256 &hashAnchor,
CAnchorsMap &mapAnchors, CAnchorsMap &mapAnchors,
CSerialsMap &mapSerials); CNullifiersMap &mapNullifiers);
//! Calculate statistics about the unspent transaction output set //! Calculate statistics about the unspent transaction output set
virtual bool GetStats(CCoinsStats &stats) const; virtual bool GetStats(CCoinsStats &stats) const;
@ -387,7 +387,7 @@ protected:
public: public:
CCoinsViewBacked(CCoinsView *viewIn); CCoinsViewBacked(CCoinsView *viewIn);
bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const; bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const;
bool GetSerial(const uint256 &serial) const; bool GetNullifier(const uint256 &nullifier) const;
bool GetCoins(const uint256 &txid, CCoins &coins) const; bool GetCoins(const uint256 &txid, CCoins &coins) const;
bool HaveCoins(const uint256 &txid) const; bool HaveCoins(const uint256 &txid) const;
uint256 GetBestBlock() const; uint256 GetBestBlock() const;
@ -397,7 +397,7 @@ public:
const uint256 &hashBlock, const uint256 &hashBlock,
const uint256 &hashAnchor, const uint256 &hashAnchor,
CAnchorsMap &mapAnchors, CAnchorsMap &mapAnchors,
CSerialsMap &mapSerials); CNullifiersMap &mapNullifiers);
bool GetStats(CCoinsStats &stats) const; bool GetStats(CCoinsStats &stats) const;
}; };
@ -440,7 +440,7 @@ protected:
mutable CCoinsMap cacheCoins; mutable CCoinsMap cacheCoins;
mutable uint256 hashAnchor; mutable uint256 hashAnchor;
mutable CAnchorsMap cacheAnchors; mutable CAnchorsMap cacheAnchors;
mutable CSerialsMap cacheSerials; mutable CNullifiersMap cacheNullifiers;
/* Cached dynamic memory usage for the inner CCoins objects. */ /* Cached dynamic memory usage for the inner CCoins objects. */
mutable size_t cachedCoinsUsage; mutable size_t cachedCoinsUsage;
@ -451,7 +451,7 @@ public:
// Standard CCoinsView methods // Standard CCoinsView methods
bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const; bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const;
bool GetSerial(const uint256 &serial) const; bool GetNullifier(const uint256 &nullifier) const;
bool GetCoins(const uint256 &txid, CCoins &coins) const; bool GetCoins(const uint256 &txid, CCoins &coins) const;
bool HaveCoins(const uint256 &txid) const; bool HaveCoins(const uint256 &txid) const;
uint256 GetBestBlock() const; uint256 GetBestBlock() const;
@ -461,7 +461,7 @@ public:
const uint256 &hashBlock, const uint256 &hashBlock,
const uint256 &hashAnchor, const uint256 &hashAnchor,
CAnchorsMap &mapAnchors, CAnchorsMap &mapAnchors,
CSerialsMap &mapSerials); CNullifiersMap &mapNullifiers);
// Adds the tree to mapAnchors and sets the current commitment // Adds the tree to mapAnchors and sets the current commitment
@ -472,8 +472,8 @@ public:
// the new current root. // the new current root.
void PopAnchor(const uint256 &rt); void PopAnchor(const uint256 &rt);
// Marks a serial as spent or not. // Marks a nullifier as spent or not.
void SetSerial(const uint256 &serial, bool spent); void SetNullifier(const uint256 &nullifier, bool spent);
/** /**
* Return a pointer to CCoins in the cache, or NULL if not found. This is * Return a pointer to CCoins in the cache, or NULL if not found. This is
@ -515,8 +515,8 @@ public:
//! Check whether all prevouts of the transaction are present in the UTXO set represented by this view //! Check whether all prevouts of the transaction are present in the UTXO set represented by this view
bool HaveInputs(const CTransaction& tx) const; bool HaveInputs(const CTransaction& tx) const;
//! Check whether all pour requirements (anchors/serials) are satisfied //! Check whether all joinsplit requirements (anchors/nullifiers) are satisfied
bool HavePourRequirements(const CTransaction& tx) const; bool HaveJoinSplitRequirements(const CTransaction& tx) const;
//! Return priority of tx at height nHeight //! Return priority of tx at height nHeight
double GetPriority(const CTransaction &tx, int nHeight) const; double GetPriority(const CTransaction &tx, int nHeight) const;

View File

@ -11,15 +11,15 @@ TEST(checktransaction_tests, check_vpub_not_both_nonzero) {
tx.nVersion = 2; tx.nVersion = 2;
{ {
// Ensure that values within the pour are well-formed. // Ensure that values within the joinsplit are well-formed.
CMutableTransaction newTx(tx); CMutableTransaction newTx(tx);
CValidationState state; CValidationState state;
newTx.vpour.push_back(CPourTx()); newTx.vjoinsplit.push_back(JSDescription());
CPourTx *pourtx = &newTx.vpour[0]; JSDescription *jsdesc = &newTx.vjoinsplit[0];
pourtx->vpub_old = 1; jsdesc->vpub_old = 1;
pourtx->vpub_new = 1; jsdesc->vpub_new = 1;
EXPECT_FALSE(CheckTransactionWithoutProofVerification(newTx, state)); EXPECT_FALSE(CheckTransactionWithoutProofVerification(newTx, state));
EXPECT_EQ(state.GetRejectReason(), "bad-txns-vpubs-both-nonzero"); EXPECT_EQ(state.GetRejectReason(), "bad-txns-vpubs-both-nonzero");
@ -55,11 +55,11 @@ CMutableTransaction GetValidTransaction() {
// mtx.vout[0].scriptPubKey = // mtx.vout[0].scriptPubKey =
mtx.vout[0].nValue = 0; mtx.vout[0].nValue = 0;
mtx.vout[1].nValue = 0; mtx.vout[1].nValue = 0;
mtx.vpour.resize(2); mtx.vjoinsplit.resize(2);
mtx.vpour[0].serials.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); mtx.vjoinsplit[0].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000");
mtx.vpour[0].serials.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); mtx.vjoinsplit[0].nullifiers.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000001");
mtx.vpour[1].serials.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000002"); mtx.vjoinsplit[1].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000002");
mtx.vpour[1].serials.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000003"); mtx.vjoinsplit[1].nullifiers.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000003");
// Generate an ephemeral keypair. // Generate an ephemeral keypair.
@ -96,7 +96,7 @@ TEST(checktransaction_tests, valid_transaction) {
TEST(checktransaction_tests, bad_txns_vin_empty) { TEST(checktransaction_tests, bad_txns_vin_empty) {
CMutableTransaction mtx = GetValidTransaction(); CMutableTransaction mtx = GetValidTransaction();
mtx.vpour.resize(0); mtx.vjoinsplit.resize(0);
mtx.vin.resize(0); mtx.vin.resize(0);
CTransaction tx(mtx); CTransaction tx(mtx);
@ -107,7 +107,7 @@ TEST(checktransaction_tests, bad_txns_vin_empty) {
TEST(checktransaction_tests, bad_txns_vout_empty) { TEST(checktransaction_tests, bad_txns_vout_empty) {
CMutableTransaction mtx = GetValidTransaction(); CMutableTransaction mtx = GetValidTransaction();
mtx.vpour.resize(0); mtx.vjoinsplit.resize(0);
mtx.vout.resize(0); mtx.vout.resize(0);
CTransaction tx(mtx); CTransaction tx(mtx);
@ -171,7 +171,7 @@ TEST(checktransaction_tests, bad_txns_txouttotal_toolarge_outputs) {
TEST(checktransaction_tests, bad_txns_txouttotal_toolarge_joinsplit) { TEST(checktransaction_tests, bad_txns_txouttotal_toolarge_joinsplit) {
CMutableTransaction mtx = GetValidTransaction(); CMutableTransaction mtx = GetValidTransaction();
mtx.vout[0].nValue = 1; mtx.vout[0].nValue = 1;
mtx.vpour[0].vpub_new = MAX_MONEY; mtx.vjoinsplit[0].vpub_new = MAX_MONEY;
CTransaction tx(mtx); CTransaction tx(mtx);
@ -182,7 +182,7 @@ TEST(checktransaction_tests, bad_txns_txouttotal_toolarge_joinsplit) {
TEST(checktransaction_tests, bad_txns_vpub_old_negative) { TEST(checktransaction_tests, bad_txns_vpub_old_negative) {
CMutableTransaction mtx = GetValidTransaction(); CMutableTransaction mtx = GetValidTransaction();
mtx.vpour[0].vpub_old = -1; mtx.vjoinsplit[0].vpub_old = -1;
CTransaction tx(mtx); CTransaction tx(mtx);
@ -193,7 +193,7 @@ TEST(checktransaction_tests, bad_txns_vpub_old_negative) {
TEST(checktransaction_tests, bad_txns_vpub_new_negative) { TEST(checktransaction_tests, bad_txns_vpub_new_negative) {
CMutableTransaction mtx = GetValidTransaction(); CMutableTransaction mtx = GetValidTransaction();
mtx.vpour[0].vpub_new = -1; mtx.vjoinsplit[0].vpub_new = -1;
CTransaction tx(mtx); CTransaction tx(mtx);
@ -204,7 +204,7 @@ TEST(checktransaction_tests, bad_txns_vpub_new_negative) {
TEST(checktransaction_tests, bad_txns_vpub_old_toolarge) { TEST(checktransaction_tests, bad_txns_vpub_old_toolarge) {
CMutableTransaction mtx = GetValidTransaction(); CMutableTransaction mtx = GetValidTransaction();
mtx.vpour[0].vpub_old = MAX_MONEY + 1; mtx.vjoinsplit[0].vpub_old = MAX_MONEY + 1;
CTransaction tx(mtx); CTransaction tx(mtx);
@ -215,7 +215,7 @@ TEST(checktransaction_tests, bad_txns_vpub_old_toolarge) {
TEST(checktransaction_tests, bad_txns_vpub_new_toolarge) { TEST(checktransaction_tests, bad_txns_vpub_new_toolarge) {
CMutableTransaction mtx = GetValidTransaction(); CMutableTransaction mtx = GetValidTransaction();
mtx.vpour[0].vpub_new = MAX_MONEY + 1; mtx.vjoinsplit[0].vpub_new = MAX_MONEY + 1;
CTransaction tx(mtx); CTransaction tx(mtx);
@ -226,8 +226,8 @@ TEST(checktransaction_tests, bad_txns_vpub_new_toolarge) {
TEST(checktransaction_tests, bad_txns_vpubs_both_nonzero) { TEST(checktransaction_tests, bad_txns_vpubs_both_nonzero) {
CMutableTransaction mtx = GetValidTransaction(); CMutableTransaction mtx = GetValidTransaction();
mtx.vpour[0].vpub_old = 1; mtx.vjoinsplit[0].vpub_old = 1;
mtx.vpour[0].vpub_new = 1; mtx.vjoinsplit[0].vpub_new = 1;
CTransaction tx(mtx); CTransaction tx(mtx);
@ -248,43 +248,43 @@ TEST(checktransaction_tests, bad_txns_inputs_duplicate) {
CheckTransactionWithoutProofVerification(tx, state); CheckTransactionWithoutProofVerification(tx, state);
} }
TEST(checktransaction_tests, bad_pours_serials_duplicate_same_pour) { TEST(checktransaction_tests, bad_joinsplits_nullifiers_duplicate_same_joinsplit) {
CMutableTransaction mtx = GetValidTransaction(); CMutableTransaction mtx = GetValidTransaction();
mtx.vpour[0].serials.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); mtx.vjoinsplit[0].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000");
mtx.vpour[0].serials.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); mtx.vjoinsplit[0].nullifiers.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000000");
CTransaction tx(mtx); CTransaction tx(mtx);
MockCValidationState state; MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-pours-serials-duplicate", false)).Times(1); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-joinsplits-nullifiers-duplicate", false)).Times(1);
CheckTransactionWithoutProofVerification(tx, state); CheckTransactionWithoutProofVerification(tx, state);
} }
TEST(checktransaction_tests, bad_pours_serials_duplicate_different_pour) { TEST(checktransaction_tests, bad_joinsplits_nullifiers_duplicate_different_joinsplit) {
CMutableTransaction mtx = GetValidTransaction(); CMutableTransaction mtx = GetValidTransaction();
mtx.vpour[0].serials.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); mtx.vjoinsplit[0].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000");
mtx.vpour[1].serials.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); mtx.vjoinsplit[1].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000");
CTransaction tx(mtx); CTransaction tx(mtx);
MockCValidationState state; MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-pours-serials-duplicate", false)).Times(1); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-joinsplits-nullifiers-duplicate", false)).Times(1);
CheckTransactionWithoutProofVerification(tx, state); CheckTransactionWithoutProofVerification(tx, state);
} }
TEST(checktransaction_tests, bad_cb_has_pours) { TEST(checktransaction_tests, bad_cb_has_joinsplits) {
CMutableTransaction mtx = GetValidTransaction(); CMutableTransaction mtx = GetValidTransaction();
// Make it a coinbase. // Make it a coinbase.
mtx.vin.resize(1); mtx.vin.resize(1);
mtx.vin[0].prevout.SetNull(); mtx.vin[0].prevout.SetNull();
mtx.vpour.resize(1); mtx.vjoinsplit.resize(1);
CTransaction tx(mtx); CTransaction tx(mtx);
EXPECT_TRUE(tx.IsCoinBase()); EXPECT_TRUE(tx.IsCoinBase());
MockCValidationState state; MockCValidationState state;
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-has-pours", false)).Times(1); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-has-joinsplits", false)).Times(1);
CheckTransactionWithoutProofVerification(tx, state); CheckTransactionWithoutProofVerification(tx, state);
} }
@ -294,7 +294,7 @@ TEST(checktransaction_tests, bad_cb_empty_scriptsig) {
mtx.vin.resize(1); mtx.vin.resize(1);
mtx.vin[0].prevout.SetNull(); mtx.vin[0].prevout.SetNull();
mtx.vpour.resize(0); mtx.vjoinsplit.resize(0);
CTransaction tx(mtx); CTransaction tx(mtx);
EXPECT_TRUE(tx.IsCoinBase()); EXPECT_TRUE(tx.IsCoinBase());

View File

@ -876,10 +876,10 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
return false; return false;
} else { } else {
// Ensure that zk-SNARKs verify // Ensure that zk-SNARKs verify
BOOST_FOREACH(const CPourTx &pour, tx.vpour) { BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
if (!pour.Verify(*pzcashParams, tx.joinSplitPubKey)) { if (!joinsplit.Verify(*pzcashParams, tx.joinSplitPubKey)) {
return state.DoS(100, error("CheckTransaction(): pour does not verify"), return state.DoS(100, error("CheckTransaction(): joinsplit does not verify"),
REJECT_INVALID, "bad-txns-pour-verification-failed"); REJECT_INVALID, "bad-txns-joinsplit-verification-failed");
} }
} }
return true; return true;
@ -891,11 +891,11 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
// Basic checks that don't depend on any context // Basic checks that don't depend on any context
// Transactions can contain empty `vin` and `vout` so long as // Transactions can contain empty `vin` and `vout` so long as
// `vpour` is non-empty. // `vjoinsplit` is non-empty.
if (tx.vin.empty() && tx.vpour.empty()) if (tx.vin.empty() && tx.vjoinsplit.empty())
return state.DoS(10, error("CheckTransaction(): vin empty"), return state.DoS(10, error("CheckTransaction(): vin empty"),
REJECT_INVALID, "bad-txns-vin-empty"); REJECT_INVALID, "bad-txns-vin-empty");
if (tx.vout.empty() && tx.vpour.empty()) if (tx.vout.empty() && tx.vjoinsplit.empty())
return state.DoS(10, error("CheckTransaction(): vout empty"), return state.DoS(10, error("CheckTransaction(): vout empty"),
REJECT_INVALID, "bad-txns-vout-empty"); REJECT_INVALID, "bad-txns-vout-empty");
@ -920,35 +920,35 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
REJECT_INVALID, "bad-txns-txouttotal-toolarge"); REJECT_INVALID, "bad-txns-txouttotal-toolarge");
} }
// Ensure that pour values are well-formed // Ensure that joinsplit values are well-formed
BOOST_FOREACH(const CPourTx& pour, tx.vpour) BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit)
{ {
if (pour.vpub_old < 0) { if (joinsplit.vpub_old < 0) {
return state.DoS(100, error("CheckTransaction(): pour.vpub_old negative"), return state.DoS(100, error("CheckTransaction(): joinsplit.vpub_old negative"),
REJECT_INVALID, "bad-txns-vpub_old-negative"); REJECT_INVALID, "bad-txns-vpub_old-negative");
} }
if (pour.vpub_new < 0) { if (joinsplit.vpub_new < 0) {
return state.DoS(100, error("CheckTransaction(): pour.vpub_new negative"), return state.DoS(100, error("CheckTransaction(): joinsplit.vpub_new negative"),
REJECT_INVALID, "bad-txns-vpub_new-negative"); REJECT_INVALID, "bad-txns-vpub_new-negative");
} }
if (pour.vpub_old > MAX_MONEY) { if (joinsplit.vpub_old > MAX_MONEY) {
return state.DoS(100, error("CheckTransaction(): pour.vpub_old too high"), return state.DoS(100, error("CheckTransaction(): joinsplit.vpub_old too high"),
REJECT_INVALID, "bad-txns-vpub_old-toolarge"); REJECT_INVALID, "bad-txns-vpub_old-toolarge");
} }
if (pour.vpub_new > MAX_MONEY) { if (joinsplit.vpub_new > MAX_MONEY) {
return state.DoS(100, error("CheckTransaction(): pour.vpub_new too high"), return state.DoS(100, error("CheckTransaction(): joinsplit.vpub_new too high"),
REJECT_INVALID, "bad-txns-vpub_new-toolarge"); REJECT_INVALID, "bad-txns-vpub_new-toolarge");
} }
if (pour.vpub_new != 0 && pour.vpub_old != 0) { if (joinsplit.vpub_new != 0 && joinsplit.vpub_old != 0) {
return state.DoS(100, error("CheckTransaction(): pour.vpub_new and pour.vpub_old both nonzero"), return state.DoS(100, error("CheckTransaction(): joinsplit.vpub_new and joinsplit.vpub_old both nonzero"),
REJECT_INVALID, "bad-txns-vpubs-both-nonzero"); REJECT_INVALID, "bad-txns-vpubs-both-nonzero");
} }
nValueOut += pour.vpub_new; nValueOut += joinsplit.vpub_new;
if (!MoneyRange(nValueOut)) { if (!MoneyRange(nValueOut)) {
return state.DoS(100, error("CheckTransaction(): txout total out of range"), return state.DoS(100, error("CheckTransaction(): txout total out of range"),
REJECT_INVALID, "bad-txns-txouttotal-toolarge"); REJECT_INVALID, "bad-txns-txouttotal-toolarge");
@ -966,26 +966,26 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
vInOutPoints.insert(txin.prevout); vInOutPoints.insert(txin.prevout);
} }
// Check for duplicate pour serials in this transaction // Check for duplicate joinsplit nullifiers in this transaction
set<uint256> vPourSerials; set<uint256> vJoinSplitNullifiers;
BOOST_FOREACH(const CPourTx& pour, tx.vpour) BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit)
{ {
BOOST_FOREACH(const uint256& serial, pour.serials) BOOST_FOREACH(const uint256& nf, joinsplit.nullifiers)
{ {
if (vPourSerials.count(serial)) if (vJoinSplitNullifiers.count(nf))
return state.DoS(100, error("CheckTransaction(): duplicate serials"), return state.DoS(100, error("CheckTransaction(): duplicate nullifiers"),
REJECT_INVALID, "bad-pours-serials-duplicate"); REJECT_INVALID, "bad-joinsplits-nullifiers-duplicate");
vPourSerials.insert(serial); vJoinSplitNullifiers.insert(nf);
} }
} }
if (tx.IsCoinBase()) if (tx.IsCoinBase())
{ {
// There should be no pours in a coinbase transaction // There should be no joinsplits in a coinbase transaction
if (tx.vpour.size() > 0) if (tx.vjoinsplit.size() > 0)
return state.DoS(100, error("CheckTransaction(): coinbase has pours"), return state.DoS(100, error("CheckTransaction(): coinbase has joinsplits"),
REJECT_INVALID, "bad-cb-has-pours"); REJECT_INVALID, "bad-cb-has-joinsplits");
if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100) if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
return state.DoS(100, error("CheckTransaction(): coinbase script size"), return state.DoS(100, error("CheckTransaction(): coinbase script size"),
@ -998,7 +998,7 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
return state.DoS(10, error("CheckTransaction(): prevout is null"), return state.DoS(10, error("CheckTransaction(): prevout is null"),
REJECT_INVALID, "bad-txns-prevout-null"); REJECT_INVALID, "bad-txns-prevout-null");
if (tx.vpour.size() > 0) { if (tx.vjoinsplit.size() > 0) {
// TODO: #966. // TODO: #966.
static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
// Empty output script. // Empty output script.
@ -1104,9 +1104,9 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
return false; return false;
} }
} }
BOOST_FOREACH(const CPourTx &pour, tx.vpour) { BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
BOOST_FOREACH(const uint256 &serial, pour.serials) { BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) {
if (pool.mapSerials.count(serial)) if (pool.mapNullifiers.count(nf))
{ {
return false; return false;
} }
@ -1144,10 +1144,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
return state.Invalid(error("AcceptToMemoryPool: inputs already spent"), return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),
REJECT_DUPLICATE, "bad-txns-inputs-spent"); REJECT_DUPLICATE, "bad-txns-inputs-spent");
// are the pour's requirements met? // are the joinsplit's requirements met?
if (!view.HavePourRequirements(tx)) if (!view.HaveJoinSplitRequirements(tx))
return state.Invalid(error("AcceptToMemoryPool: pour requirements not met"), return state.Invalid(error("AcceptToMemoryPool: joinsplit requirements not met"),
REJECT_DUPLICATE, "bad-txns-pour-requirements-not-met"); REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met");
// Bring the best block into scope // Bring the best block into scope
view.GetBestBlock(); view.GetBestBlock();
@ -1585,10 +1585,10 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
} }
} }
// spend serials // spend nullifiers
BOOST_FOREACH(const CPourTx &pour, tx.vpour) { BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
BOOST_FOREACH(const uint256 &serial, pour.serials) { BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) {
inputs.SetSerial(serial, true); inputs.SetNullifier(nf, true);
} }
} }
@ -1622,9 +1622,9 @@ bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, c
if (!inputs.HaveInputs(tx)) if (!inputs.HaveInputs(tx))
return state.Invalid(error("CheckInputs(): %s inputs unavailable", tx.GetHash().ToString())); return state.Invalid(error("CheckInputs(): %s inputs unavailable", tx.GetHash().ToString()));
// are the pour's requirements met? // are the JoinSplit's requirements met?
if (!inputs.HavePourRequirements(tx)) if (!inputs.HaveJoinSplitRequirements(tx))
return state.Invalid(error("CheckInputs(): %s pour requirements not met", tx.GetHash().ToString())); return state.Invalid(error("CheckInputs(): %s JoinSplit requirements not met", tx.GetHash().ToString()));
CAmount nValueIn = 0; CAmount nValueIn = 0;
CAmount nFees = 0; CAmount nFees = 0;
@ -1654,7 +1654,7 @@ bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, c
} }
nValueIn += tx.GetPourValueIn(); nValueIn += tx.GetJoinSplitValueIn();
if (!MoneyRange(nValueIn)) if (!MoneyRange(nValueIn))
return state.DoS(100, error("CheckInputs(): vpub_old values out of range"), return state.DoS(100, error("CheckInputs(): vpub_old values out of range"),
REJECT_INVALID, "bad-txns-inputvalues-outofrange"); REJECT_INVALID, "bad-txns-inputvalues-outofrange");
@ -1907,10 +1907,10 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
outs->Clear(); outs->Clear();
} }
// unspend serials // unspend nullifiers
BOOST_FOREACH(const CPourTx &pour, tx.vpour) { BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
BOOST_FOREACH(const uint256 &serial, pour.serials) { BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) {
view.SetSerial(serial, false); view.SetNullifier(nf, false);
} }
} }
@ -2130,10 +2130,10 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return state.DoS(100, error("ConnectBlock(): inputs missing/spent"), return state.DoS(100, error("ConnectBlock(): inputs missing/spent"),
REJECT_INVALID, "bad-txns-inputs-missingorspent"); REJECT_INVALID, "bad-txns-inputs-missingorspent");
// are the pour's requirements met? // are the JoinSplit's requirements met?
if (!view.HavePourRequirements(tx)) if (!view.HaveJoinSplitRequirements(tx))
return state.DoS(100, error("ConnectBlock(): pour requirements not met"), return state.DoS(100, error("ConnectBlock(): JoinSplit requirements not met"),
REJECT_INVALID, "bad-txns-pour-requirements-not-met"); REJECT_INVALID, "bad-txns-joinsplit-requirements-not-met");
// Add in sigops done by pay-to-script-hash inputs; // Add in sigops done by pay-to-script-hash inputs;
// this is to prevent a "rogue miner" from creating // this is to prevent a "rogue miner" from creating
@ -2157,11 +2157,11 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
} }
UpdateCoins(tx, state, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight); UpdateCoins(tx, state, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight);
BOOST_FOREACH(const CPourTx &pour, tx.vpour) { BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
BOOST_FOREACH(const uint256 &bucket_commitment, pour.commitments) { BOOST_FOREACH(const uint256 &note_commitment, joinsplit.commitments) {
// Insert the bucket commitments into our temporary tree. // Insert the note commitments into our temporary tree.
tree.append(bucket_commitment); tree.append(note_commitment);
} }
} }
@ -4733,8 +4733,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
BOOST_FOREACH(uint256 hash, vEraseQueue) BOOST_FOREACH(uint256 hash, vEraseQueue)
EraseOrphanTx(hash); EraseOrphanTx(hash);
} }
// TODO: currently, prohibit pours from entering mapOrphans // TODO: currently, prohibit joinsplits from entering mapOrphans
else if (fMissingInputs && tx.vpour.size() == 0) else if (fMissingInputs && tx.vjoinsplit.size() == 0)
{ {
AddOrphanTx(tx, pfrom->GetId()); AddOrphanTx(tx, pfrom->GetId());

View File

@ -9,7 +9,7 @@
#include "tinyformat.h" #include "tinyformat.h"
#include "utilstrencodings.h" #include "utilstrencodings.h"
CPourTx::CPourTx(ZCJoinSplit& params, JSDescription::JSDescription(ZCJoinSplit& params,
const uint256& pubKeyHash, const uint256& pubKeyHash,
const uint256& anchor, const uint256& anchor,
const boost::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs, const boost::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
@ -29,7 +29,7 @@ CPourTx::CPourTx(ZCJoinSplit& params,
pubKeyHash, pubKeyHash,
randomSeed, randomSeed,
macs, macs,
serials, nullifiers,
commitments, commitments,
vpub_old, vpub_old,
vpub_new, vpub_new,
@ -37,7 +37,7 @@ CPourTx::CPourTx(ZCJoinSplit& params,
); );
} }
bool CPourTx::Verify( bool JSDescription::Verify(
ZCJoinSplit& params, ZCJoinSplit& params,
const uint256& pubKeyHash const uint256& pubKeyHash
) const { ) const {
@ -46,7 +46,7 @@ bool CPourTx::Verify(
pubKeyHash, pubKeyHash,
randomSeed, randomSeed,
macs, macs,
serials, nullifiers,
commitments, commitments,
vpub_old, vpub_old,
vpub_new, vpub_new,
@ -54,9 +54,9 @@ bool CPourTx::Verify(
); );
} }
uint256 CPourTx::h_sig(ZCJoinSplit& params, const uint256& pubKeyHash) const uint256 JSDescription::h_sig(ZCJoinSplit& params, const uint256& pubKeyHash) const
{ {
return params.h_sig(randomSeed, serials, pubKeyHash); return params.h_sig(randomSeed, nullifiers, pubKeyHash);
} }
std::string COutPoint::ToString() const std::string COutPoint::ToString() const
@ -111,7 +111,7 @@ std::string CTxOut::ToString() const
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {} CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {}
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime),
vpour(tx.vpour), joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig) vjoinsplit(tx.vjoinsplit), joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig)
{ {
} }
@ -126,9 +126,9 @@ void CTransaction::UpdateHash() const
*const_cast<uint256*>(&hash) = SerializeHash(*this); *const_cast<uint256*>(&hash) = SerializeHash(*this);
} }
CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0), vpour(), joinSplitPubKey(), joinSplitSig() { } CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0), vjoinsplit(), joinSplitPubKey(), joinSplitSig() { }
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), vpour(tx.vpour), CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), vjoinsplit(tx.vjoinsplit),
joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig) joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig)
{ {
UpdateHash(); UpdateHash();
@ -139,7 +139,7 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) {
*const_cast<std::vector<CTxIn>*>(&vin) = tx.vin; *const_cast<std::vector<CTxIn>*>(&vin) = tx.vin;
*const_cast<std::vector<CTxOut>*>(&vout) = tx.vout; *const_cast<std::vector<CTxOut>*>(&vout) = tx.vout;
*const_cast<unsigned int*>(&nLockTime) = tx.nLockTime; *const_cast<unsigned int*>(&nLockTime) = tx.nLockTime;
*const_cast<std::vector<CPourTx>*>(&vpour) = tx.vpour; *const_cast<std::vector<JSDescription>*>(&vjoinsplit) = tx.vjoinsplit;
*const_cast<uint256*>(&joinSplitPubKey) = tx.joinSplitPubKey; *const_cast<uint256*>(&joinSplitPubKey) = tx.joinSplitPubKey;
*const_cast<joinsplit_sig_t*>(&joinSplitSig) = tx.joinSplitSig; *const_cast<joinsplit_sig_t*>(&joinSplitSig) = tx.joinSplitSig;
*const_cast<uint256*>(&hash) = tx.hash; *const_cast<uint256*>(&hash) = tx.hash;
@ -156,7 +156,7 @@ CAmount CTransaction::GetValueOut() const
throw std::runtime_error("CTransaction::GetValueOut(): value out of range"); throw std::runtime_error("CTransaction::GetValueOut(): value out of range");
} }
for (std::vector<CPourTx>::const_iterator it(vpour.begin()); it != vpour.end(); ++it) for (std::vector<JSDescription>::const_iterator it(vjoinsplit.begin()); it != vjoinsplit.end(); ++it)
{ {
// NB: vpub_old "takes" money from the value pool just as outputs do // NB: vpub_old "takes" money from the value pool just as outputs do
nValueOut += it->vpub_old; nValueOut += it->vpub_old;
@ -167,16 +167,16 @@ CAmount CTransaction::GetValueOut() const
return nValueOut; return nValueOut;
} }
CAmount CTransaction::GetPourValueIn() const CAmount CTransaction::GetJoinSplitValueIn() const
{ {
CAmount nValue = 0; CAmount nValue = 0;
for (std::vector<CPourTx>::const_iterator it(vpour.begin()); it != vpour.end(); ++it) for (std::vector<JSDescription>::const_iterator it(vjoinsplit.begin()); it != vjoinsplit.end(); ++it)
{ {
// NB: vpub_new "gives" money to the value pool just as inputs do // NB: vpub_new "gives" money to the value pool just as inputs do
nValue += it->vpub_new; nValue += it->vpub_new;
if (!MoneyRange(it->vpub_new) || !MoneyRange(nValue)) if (!MoneyRange(it->vpub_new) || !MoneyRange(nValue))
throw std::runtime_error("CTransaction::GetPourValueIn(): value out of range"); throw std::runtime_error("CTransaction::GetJoinSplitValueIn(): value out of range");
} }
return nValue; return nValue;

View File

@ -17,7 +17,7 @@
#include "zcash/Zcash.h" #include "zcash/Zcash.h"
#include "zcash/JoinSplit.hpp" #include "zcash/JoinSplit.hpp"
class CPourTx class JSDescription
{ {
public: public:
// These values 'enter from' and 'exit to' the value // These values 'enter from' and 'exit to' the value
@ -25,22 +25,22 @@ public:
CAmount vpub_old; CAmount vpub_old;
CAmount vpub_new; CAmount vpub_new;
// Pours are always anchored to a root in the bucket // JoinSplits are always anchored to a root in the note
// commitment tree at some point in the blockchain // commitment tree at some point in the blockchain
// history or in the history of the current // history or in the history of the current
// transaction. // transaction.
uint256 anchor; uint256 anchor;
// Serials are used to prevent double-spends. They // Nullifiers are used to prevent double-spends. They
// are derived from the secrets placed in the bucket // are derived from the secrets placed in the note
// and the secret spend-authority key known by the // and the secret spend-authority key known by the
// spender. // spender.
boost::array<uint256, ZC_NUM_JS_INPUTS> serials; boost::array<uint256, ZC_NUM_JS_INPUTS> nullifiers;
// Bucket commitments are introduced into the commitment // Note commitments are introduced into the commitment
// tree, blinding the public about the values and // tree, blinding the public about the values and
// destinations involved in the Pour. The presence of a // destinations involved in the JoinSplit. The presence of
// commitment in the bucket commitment tree is required // a commitment in the note commitment tree is required
// to spend it. // to spend it.
boost::array<uint256, ZC_NUM_JS_OUTPUTS> commitments; boost::array<uint256, ZC_NUM_JS_OUTPUTS> commitments;
@ -57,17 +57,17 @@ public:
uint256 randomSeed; uint256 randomSeed;
// MACs // MACs
// The verification of the pour requires these MACs // The verification of the JoinSplit requires these MACs
// to be provided as an input. // to be provided as an input.
boost::array<uint256, ZC_NUM_JS_INPUTS> macs; boost::array<uint256, ZC_NUM_JS_INPUTS> macs;
// Pour proof // JoinSplit proof
// This is a zk-SNARK which ensures that this pour is valid. // This is a zk-SNARK which ensures that this JoinSplit is valid.
boost::array<unsigned char, ZKSNARK_PROOF_SIZE> proof; boost::array<unsigned char, ZKSNARK_PROOF_SIZE> proof;
CPourTx(): vpub_old(0), vpub_new(0) { } JSDescription(): vpub_old(0), vpub_new(0) { }
CPourTx(ZCJoinSplit& params, JSDescription(ZCJoinSplit& params,
const uint256& pubKeyHash, const uint256& pubKeyHash,
const uint256& rt, const uint256& rt,
const boost::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs, const boost::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
@ -76,7 +76,7 @@ public:
CAmount vpub_new CAmount vpub_new
); );
// Verifies that the pour proof is correct. // Verifies that the JoinSplit proof is correct.
bool Verify(ZCJoinSplit& params, const uint256& pubKeyHash) const; bool Verify(ZCJoinSplit& params, const uint256& pubKeyHash) const;
// Returns the calculated h_sig // Returns the calculated h_sig
@ -89,7 +89,7 @@ public:
READWRITE(vpub_old); READWRITE(vpub_old);
READWRITE(vpub_new); READWRITE(vpub_new);
READWRITE(anchor); READWRITE(anchor);
READWRITE(serials); READWRITE(nullifiers);
READWRITE(commitments); READWRITE(commitments);
READWRITE(ephemeralKey); READWRITE(ephemeralKey);
READWRITE(ciphertexts); READWRITE(ciphertexts);
@ -98,13 +98,13 @@ public:
READWRITE(proof); READWRITE(proof);
} }
friend bool operator==(const CPourTx& a, const CPourTx& b) friend bool operator==(const JSDescription& a, const JSDescription& b)
{ {
return ( return (
a.vpub_old == b.vpub_old && a.vpub_old == b.vpub_old &&
a.vpub_new == b.vpub_new && a.vpub_new == b.vpub_new &&
a.anchor == b.anchor && a.anchor == b.anchor &&
a.serials == b.serials && a.nullifiers == b.nullifiers &&
a.commitments == b.commitments && a.commitments == b.commitments &&
a.ephemeralKey == b.ephemeralKey && a.ephemeralKey == b.ephemeralKey &&
a.ciphertexts == b.ciphertexts && a.ciphertexts == b.ciphertexts &&
@ -114,7 +114,7 @@ public:
); );
} }
friend bool operator!=(const CPourTx& a, const CPourTx& b) friend bool operator!=(const JSDescription& a, const JSDescription& b)
{ {
return !(a == b); return !(a == b);
} }
@ -303,7 +303,7 @@ public:
const std::vector<CTxIn> vin; const std::vector<CTxIn> vin;
const std::vector<CTxOut> vout; const std::vector<CTxOut> vout;
const uint32_t nLockTime; const uint32_t nLockTime;
const std::vector<CPourTx> vpour; const std::vector<JSDescription> vjoinsplit;
const uint256 joinSplitPubKey; const uint256 joinSplitPubKey;
const joinsplit_sig_t joinSplitSig; const joinsplit_sig_t joinSplitSig;
@ -325,8 +325,8 @@ public:
READWRITE(*const_cast<std::vector<CTxOut>*>(&vout)); READWRITE(*const_cast<std::vector<CTxOut>*>(&vout));
READWRITE(*const_cast<uint32_t*>(&nLockTime)); READWRITE(*const_cast<uint32_t*>(&nLockTime));
if (nVersion >= 2) { if (nVersion >= 2) {
READWRITE(*const_cast<std::vector<CPourTx>*>(&vpour)); READWRITE(*const_cast<std::vector<JSDescription>*>(&vjoinsplit));
if (vpour.size() > 0) { if (vjoinsplit.size() > 0) {
READWRITE(*const_cast<uint256*>(&joinSplitPubKey)); READWRITE(*const_cast<uint256*>(&joinSplitPubKey));
READWRITE(*const_cast<joinsplit_sig_t*>(&joinSplitSig)); READWRITE(*const_cast<joinsplit_sig_t*>(&joinSplitSig));
} }
@ -348,8 +348,8 @@ public:
// GetValueIn() is a method on CCoinsViewCache, because // GetValueIn() is a method on CCoinsViewCache, because
// inputs must be known to compute value in. // inputs must be known to compute value in.
// Return sum of pour vpub_new // Return sum of JoinSplit vpub_new
CAmount GetPourValueIn() const; CAmount GetJoinSplitValueIn() const;
// Compute priority, given priority of inputs and (optionally) tx size // Compute priority, given priority of inputs and (optionally) tx size
double ComputePriority(double dPriorityInputs, unsigned int nTxSize=0) const; double ComputePriority(double dPriorityInputs, unsigned int nTxSize=0) const;
@ -382,7 +382,7 @@ struct CMutableTransaction
std::vector<CTxIn> vin; std::vector<CTxIn> vin;
std::vector<CTxOut> vout; std::vector<CTxOut> vout;
uint32_t nLockTime; uint32_t nLockTime;
std::vector<CPourTx> vpour; std::vector<JSDescription> vjoinsplit;
uint256 joinSplitPubKey; uint256 joinSplitPubKey;
CTransaction::joinsplit_sig_t joinSplitSig; CTransaction::joinsplit_sig_t joinSplitSig;
@ -399,8 +399,8 @@ struct CMutableTransaction
READWRITE(vout); READWRITE(vout);
READWRITE(nLockTime); READWRITE(nLockTime);
if (nVersion >= 2) { if (nVersion >= 2) {
READWRITE(vpour); READWRITE(vjoinsplit);
if (vpour.size() > 0) { if (vjoinsplit.size() > 0) {
READWRITE(joinSplitPubKey); READWRITE(joinSplitPubKey);
READWRITE(joinSplitSig); READWRITE(joinSplitSig);
} }

View File

@ -91,10 +91,10 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "estimatepriority", 0 }, { "estimatepriority", 0 },
{ "prioritisetransaction", 1 }, { "prioritisetransaction", 1 },
{ "prioritisetransaction", 2 }, { "prioritisetransaction", 2 },
{ "zcrawpour", 1 }, { "zcrawjoinsplit", 1 },
{ "zcrawpour", 2 }, { "zcrawjoinsplit", 2 },
{ "zcrawpour", 3 }, { "zcrawjoinsplit", 3 },
{ "zcrawpour", 4 }, { "zcrawjoinsplit", 4 },
{ "zcbenchmark", 1 }, { "zcbenchmark", 1 },
{ "getblocksubsidy", 0} { "getblocksubsidy", 0}
}; };

View File

@ -90,48 +90,48 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
} }
entry.push_back(Pair("vout", vout)); entry.push_back(Pair("vout", vout));
Array vpour; Array vjoinsplit;
for (unsigned int i = 0; i < tx.vpour.size(); i++) { for (unsigned int i = 0; i < tx.vjoinsplit.size(); i++) {
const CPourTx& pourtx = tx.vpour[i]; const JSDescription& jsdescription = tx.vjoinsplit[i];
Object pour; Object joinsplit;
pour.push_back(Pair("anchor", pourtx.anchor.GetHex())); joinsplit.push_back(Pair("anchor", jsdescription.anchor.GetHex()));
{ {
Array serials; Array nullifiers;
BOOST_FOREACH(const uint256 serial, pourtx.serials) { BOOST_FOREACH(const uint256 nf, jsdescription.nullifiers) {
serials.push_back(serial.GetHex()); nullifiers.push_back(nf.GetHex());
} }
pour.push_back(Pair("serials", serials)); joinsplit.push_back(Pair("nullifiers", nullifiers));
} }
{ {
Array commitments; Array commitments;
BOOST_FOREACH(const uint256 commitment, pourtx.commitments) { BOOST_FOREACH(const uint256 commitment, jsdescription.commitments) {
commitments.push_back(commitment.GetHex()); commitments.push_back(commitment.GetHex());
} }
pour.push_back(Pair("commitments", commitments)); joinsplit.push_back(Pair("commitments", commitments));
} }
{ {
Array macs; Array macs;
BOOST_FOREACH(const uint256 mac, pourtx.macs) { BOOST_FOREACH(const uint256 mac, jsdescription.macs) {
macs.push_back(mac.GetHex()); macs.push_back(mac.GetHex());
} }
pour.push_back(Pair("macs", macs)); joinsplit.push_back(Pair("macs", macs));
} }
pour.push_back(Pair("vpub_old", ValueFromAmount(pourtx.vpub_old))); joinsplit.push_back(Pair("vpub_old", ValueFromAmount(jsdescription.vpub_old)));
pour.push_back(Pair("vpub_new", ValueFromAmount(pourtx.vpub_new))); joinsplit.push_back(Pair("vpub_new", ValueFromAmount(jsdescription.vpub_new)));
// TODO: #808 // TODO: #808
uint256 pubKeyHash; uint256 pubKeyHash;
pour.push_back(Pair("valid", pourtx.Verify(*pzcashParams, pubKeyHash))); joinsplit.push_back(Pair("valid", jsdescription.Verify(*pzcashParams, pubKeyHash)));
vpour.push_back(pour); vjoinsplit.push_back(joinsplit);
} }
entry.push_back(Pair("vpour", vpour)); entry.push_back(Pair("vjoinsplit", vjoinsplit));
if (!hashBlock.IsNull()) { if (!hashBlock.IsNull()) {
entry.push_back(Pair("blockhash", hashBlock.GetHex())); entry.push_back(Pair("blockhash", hashBlock.GetHex()));

View File

@ -379,7 +379,7 @@ static const CRPCCommand vRPCCommands[] =
{ "wallet", "walletpassphrase", &walletpassphrase, true }, { "wallet", "walletpassphrase", &walletpassphrase, true },
{ "wallet", "zcbenchmark", &zc_benchmark, true }, { "wallet", "zcbenchmark", &zc_benchmark, true },
{ "wallet", "zcrawkeygen", &zc_raw_keygen, true }, { "wallet", "zcrawkeygen", &zc_raw_keygen, true },
{ "wallet", "zcrawpour", &zc_raw_pour, true }, { "wallet", "zcrawjoinsplit", &zc_raw_joinsplit, true },
{ "wallet", "zcrawreceive", &zc_raw_receive, true } { "wallet", "zcrawreceive", &zc_raw_receive, true }
#endif // ENABLE_WALLET #endif // ENABLE_WALLET
}; };

View File

@ -210,7 +210,7 @@ extern json_spirit::Value setmocktime(const json_spirit::Array& params, bool fHe
extern json_spirit::Value resendwallettransactions(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value resendwallettransactions(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value zc_benchmark(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value zc_benchmark(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value zc_raw_keygen(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value zc_raw_keygen(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value zc_raw_pour(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value zc_raw_joinsplit(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value zc_raw_receive(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value zc_raw_receive(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getrawtransaction(const json_spirit::Array& params, bool fHelp); // in rcprawtransaction.cpp extern json_spirit::Value getrawtransaction(const json_spirit::Array& params, bool fHelp); // in rcprawtransaction.cpp

View File

@ -1072,7 +1072,7 @@ public:
// Serialize nLockTime // Serialize nLockTime
::Serialize(s, txTo.nLockTime, nType, nVersion); ::Serialize(s, txTo.nLockTime, nType, nVersion);
// Serialize vpour // Serialize vjoinsplit
if (txTo.nVersion >= 2) { if (txTo.nVersion >= 2) {
// //
// SIGHASH_* functions will hash portions of // SIGHASH_* functions will hash portions of
@ -1080,8 +1080,8 @@ public:
// keeps the JoinSplit cryptographically bound // keeps the JoinSplit cryptographically bound
// to the transaction. // to the transaction.
// //
::Serialize(s, txTo.vpour, nType, nVersion); ::Serialize(s, txTo.vjoinsplit, nType, nVersion);
if (txTo.vpour.size() > 0) { if (txTo.vjoinsplit.size() > 0) {
::Serialize(s, txTo.joinSplitPubKey, nType, nVersion); ::Serialize(s, txTo.joinSplitPubKey, nType, nVersion);
CTransaction::joinsplit_sig_t nullSig = {}; CTransaction::joinsplit_sig_t nullSig = {};

View File

@ -24,7 +24,7 @@ class CCoinsViewTest : public CCoinsView
uint256 hashBestAnchor_; uint256 hashBestAnchor_;
std::map<uint256, CCoins> map_; std::map<uint256, CCoins> map_;
std::map<uint256, ZCIncrementalMerkleTree> mapAnchors_; std::map<uint256, ZCIncrementalMerkleTree> mapAnchors_;
std::map<uint256, bool> mapSerials_; std::map<uint256, bool> mapNullifiers_;
public: public:
CCoinsViewTest() { CCoinsViewTest() {
@ -47,11 +47,11 @@ public:
} }
} }
bool GetSerial(const uint256 &serial) const bool GetNullifier(const uint256 &nf) const
{ {
std::map<uint256, bool>::const_iterator it = mapSerials_.find(serial); std::map<uint256, bool>::const_iterator it = mapNullifiers_.find(nf);
if (it == mapSerials_.end()) { if (it == mapNullifiers_.end()) {
return false; return false;
} else { } else {
// The map shouldn't contain any false entries. // The map shouldn't contain any false entries.
@ -88,7 +88,7 @@ public:
const uint256& hashBlock, const uint256& hashBlock,
const uint256& hashAnchor, const uint256& hashAnchor,
CAnchorsMap& mapAnchors, CAnchorsMap& mapAnchors,
CSerialsMap& mapSerials) CNullifiersMap& mapNullifiers)
{ {
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); ) { for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); ) {
map_[it->first] = it->second.coins; map_[it->first] = it->second.coins;
@ -109,17 +109,17 @@ public:
} }
mapAnchors.erase(it++); mapAnchors.erase(it++);
} }
for (CSerialsMap::iterator it = mapSerials.begin(); it != mapSerials.end(); ) { for (CNullifiersMap::iterator it = mapNullifiers.begin(); it != mapNullifiers.end(); ) {
if (it->second.entered) { if (it->second.entered) {
mapSerials_[it->first] = true; mapNullifiers_[it->first] = true;
} else { } else {
mapSerials_.erase(it->first); mapNullifiers_.erase(it->first);
} }
mapSerials.erase(it++); mapNullifiers.erase(it++);
} }
mapCoins.clear(); mapCoins.clear();
mapAnchors.clear(); mapAnchors.clear();
mapSerials.clear(); mapNullifiers.clear();
hashBestBlock_ = hashBlock; hashBestBlock_ = hashBlock;
hashBestAnchor_ = hashAnchor; hashBestAnchor_ = hashAnchor;
return true; return true;
@ -138,7 +138,7 @@ public:
// Manually recompute the dynamic usage of the whole data, and compare it. // Manually recompute the dynamic usage of the whole data, and compare it.
size_t ret = memusage::DynamicUsage(cacheCoins) + size_t ret = memusage::DynamicUsage(cacheCoins) +
memusage::DynamicUsage(cacheAnchors) + memusage::DynamicUsage(cacheAnchors) +
memusage::DynamicUsage(cacheSerials); memusage::DynamicUsage(cacheNullifiers);
for (CCoinsMap::iterator it = cacheCoins.begin(); it != cacheCoins.end(); it++) { for (CCoinsMap::iterator it = cacheCoins.begin(); it != cacheCoins.end(); it++) {
ret += memusage::DynamicUsage(it->second.coins); ret += memusage::DynamicUsage(it->second.coins);
} }
@ -163,28 +163,28 @@ uint256 appendRandomCommitment(ZCIncrementalMerkleTree &tree)
BOOST_FIXTURE_TEST_SUITE(coins_tests, BasicTestingSetup) BOOST_FIXTURE_TEST_SUITE(coins_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(serials_test) BOOST_AUTO_TEST_CASE(nullifiers_test)
{ {
CCoinsViewTest base; CCoinsViewTest base;
CCoinsViewCacheTest cache(&base); CCoinsViewCacheTest cache(&base);
uint256 myserial = GetRandHash(); uint256 nf = GetRandHash();
BOOST_CHECK(!cache.GetSerial(myserial)); BOOST_CHECK(!cache.GetNullifier(nf));
cache.SetSerial(myserial, true); cache.SetNullifier(nf, true);
BOOST_CHECK(cache.GetSerial(myserial)); BOOST_CHECK(cache.GetNullifier(nf));
cache.Flush(); cache.Flush();
CCoinsViewCacheTest cache2(&base); CCoinsViewCacheTest cache2(&base);
BOOST_CHECK(cache2.GetSerial(myserial)); BOOST_CHECK(cache2.GetNullifier(nf));
cache2.SetSerial(myserial, false); cache2.SetNullifier(nf, false);
BOOST_CHECK(!cache2.GetSerial(myserial)); BOOST_CHECK(!cache2.GetNullifier(nf));
cache2.Flush(); cache2.Flush();
CCoinsViewCacheTest cache3(&base); CCoinsViewCacheTest cache3(&base);
BOOST_CHECK(!cache3.GetSerial(myserial)); BOOST_CHECK(!cache3.GetNullifier(nf));
} }
BOOST_AUTO_TEST_CASE(anchors_flush_test) BOOST_AUTO_TEST_CASE(anchors_flush_test)
@ -217,80 +217,80 @@ BOOST_AUTO_TEST_CASE(anchors_flush_test)
} }
} }
BOOST_AUTO_TEST_CASE(chained_pours) BOOST_AUTO_TEST_CASE(chained_joinsplits)
{ {
CCoinsViewTest base; CCoinsViewTest base;
CCoinsViewCacheTest cache(&base); CCoinsViewCacheTest cache(&base);
ZCIncrementalMerkleTree tree; ZCIncrementalMerkleTree tree;
CPourTx ptx1; JSDescription js1;
ptx1.anchor = tree.root(); js1.anchor = tree.root();
ptx1.commitments[0] = appendRandomCommitment(tree); js1.commitments[0] = appendRandomCommitment(tree);
ptx1.commitments[1] = appendRandomCommitment(tree); js1.commitments[1] = appendRandomCommitment(tree);
// Although it's not possible given our assumptions, if // Although it's not possible given our assumptions, if
// two pours create the same treestate twice, we should // two joinsplits create the same treestate twice, we should
// still be able to anchor to it. // still be able to anchor to it.
CPourTx ptx1b; JSDescription js1b;
ptx1b.anchor = tree.root(); js1b.anchor = tree.root();
ptx1b.commitments[0] = ptx1.commitments[0]; js1b.commitments[0] = js1.commitments[0];
ptx1b.commitments[1] = ptx1.commitments[1]; js1b.commitments[1] = js1.commitments[1];
CPourTx ptx2; JSDescription js2;
CPourTx ptx3; JSDescription js3;
ptx2.anchor = tree.root(); js2.anchor = tree.root();
ptx3.anchor = tree.root(); js3.anchor = tree.root();
ptx2.commitments[0] = appendRandomCommitment(tree); js2.commitments[0] = appendRandomCommitment(tree);
ptx2.commitments[1] = appendRandomCommitment(tree); js2.commitments[1] = appendRandomCommitment(tree);
ptx3.commitments[0] = appendRandomCommitment(tree); js3.commitments[0] = appendRandomCommitment(tree);
ptx3.commitments[1] = appendRandomCommitment(tree); js3.commitments[1] = appendRandomCommitment(tree);
{ {
CMutableTransaction mtx; CMutableTransaction mtx;
mtx.vpour.push_back(ptx2); mtx.vjoinsplit.push_back(js2);
BOOST_CHECK(!cache.HavePourRequirements(mtx)); BOOST_CHECK(!cache.HaveJoinSplitRequirements(mtx));
} }
{ {
// ptx2 is trying to anchor to ptx1 but ptx1 // js2 is trying to anchor to js1 but js1
// appears afterwards -- not a permitted ordering // appears afterwards -- not a permitted ordering
CMutableTransaction mtx; CMutableTransaction mtx;
mtx.vpour.push_back(ptx2); mtx.vjoinsplit.push_back(js2);
mtx.vpour.push_back(ptx1); mtx.vjoinsplit.push_back(js1);
BOOST_CHECK(!cache.HavePourRequirements(mtx)); BOOST_CHECK(!cache.HaveJoinSplitRequirements(mtx));
} }
{ {
CMutableTransaction mtx; CMutableTransaction mtx;
mtx.vpour.push_back(ptx1); mtx.vjoinsplit.push_back(js1);
mtx.vpour.push_back(ptx2); mtx.vjoinsplit.push_back(js2);
BOOST_CHECK(cache.HavePourRequirements(mtx)); BOOST_CHECK(cache.HaveJoinSplitRequirements(mtx));
} }
{ {
CMutableTransaction mtx; CMutableTransaction mtx;
mtx.vpour.push_back(ptx1); mtx.vjoinsplit.push_back(js1);
mtx.vpour.push_back(ptx2); mtx.vjoinsplit.push_back(js2);
mtx.vpour.push_back(ptx3); mtx.vjoinsplit.push_back(js3);
BOOST_CHECK(cache.HavePourRequirements(mtx)); BOOST_CHECK(cache.HaveJoinSplitRequirements(mtx));
} }
{ {
CMutableTransaction mtx; CMutableTransaction mtx;
mtx.vpour.push_back(ptx1); mtx.vjoinsplit.push_back(js1);
mtx.vpour.push_back(ptx1b); mtx.vjoinsplit.push_back(js1b);
mtx.vpour.push_back(ptx2); mtx.vjoinsplit.push_back(js2);
mtx.vpour.push_back(ptx3); mtx.vjoinsplit.push_back(js3);
BOOST_CHECK(cache.HavePourRequirements(mtx)); BOOST_CHECK(cache.HaveJoinSplitRequirements(mtx));
} }
} }

View File

@ -105,7 +105,7 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
tx.nLockTime = (insecure_rand() % 2) ? insecure_rand() : 0; tx.nLockTime = (insecure_rand() % 2) ? insecure_rand() : 0;
int ins = (insecure_rand() % 4) + 1; int ins = (insecure_rand() % 4) + 1;
int outs = fSingle ? ins : (insecure_rand() % 4) + 1; int outs = fSingle ? ins : (insecure_rand() % 4) + 1;
int pours = (insecure_rand() % 4); int joinsplits = (insecure_rand() % 4);
for (int in = 0; in < ins; in++) { for (int in = 0; in < ins; in++) {
tx.vin.push_back(CTxIn()); tx.vin.push_back(CTxIn());
CTxIn &txin = tx.vin.back(); CTxIn &txin = tx.vin.back();
@ -121,26 +121,26 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
RandomScript(txout.scriptPubKey); RandomScript(txout.scriptPubKey);
} }
if (tx.nVersion >= 2) { if (tx.nVersion >= 2) {
for (int pour = 0; pour < pours; pour++) { for (int js = 0; js < joinsplits; js++) {
CPourTx pourtx; JSDescription jsdesc;
if (insecure_rand() % 2 == 0) { if (insecure_rand() % 2 == 0) {
pourtx.vpub_old = insecure_rand() % 100000000; jsdesc.vpub_old = insecure_rand() % 100000000;
} else { } else {
pourtx.vpub_new = insecure_rand() % 100000000; jsdesc.vpub_new = insecure_rand() % 100000000;
} }
pourtx.anchor = GetRandHash(); jsdesc.anchor = GetRandHash();
pourtx.serials[0] = GetRandHash(); jsdesc.nullifiers[0] = GetRandHash();
pourtx.serials[1] = GetRandHash(); jsdesc.nullifiers[1] = GetRandHash();
pourtx.ephemeralKey = GetRandHash(); jsdesc.ephemeralKey = GetRandHash();
pourtx.randomSeed = GetRandHash(); jsdesc.randomSeed = GetRandHash();
randombytes_buf(pourtx.ciphertexts[0].begin(), pourtx.ciphertexts[0].size()); randombytes_buf(jsdesc.ciphertexts[0].begin(), jsdesc.ciphertexts[0].size());
randombytes_buf(pourtx.ciphertexts[1].begin(), pourtx.ciphertexts[1].size()); randombytes_buf(jsdesc.ciphertexts[1].begin(), jsdesc.ciphertexts[1].size());
randombytes_buf(pourtx.proof.begin(), pourtx.proof.size()); randombytes_buf(jsdesc.proof.begin(), jsdesc.proof.size());
pourtx.macs[0] = GetRandHash(); jsdesc.macs[0] = GetRandHash();
pourtx.macs[1] = GetRandHash(); jsdesc.macs[1] = GetRandHash();
tx.vpour.push_back(pourtx); tx.vjoinsplit.push_back(jsdesc);
} }
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];

View File

@ -291,9 +291,9 @@ SetupDummyInputs(CBasicKeyStore& keystoreRet, CCoinsViewCache& coinsRet)
return dummyTransactions; return dummyTransactions;
} }
BOOST_AUTO_TEST_CASE(test_basic_pour_verification) BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification)
{ {
// We only check that pours are constructed properly // We only check that joinsplits are constructed properly
// and verify properly here. libsnark tends to segfault // and verify properly here. libsnark tends to segfault
// when our snarks or what-have-you are invalid, so // when our snarks or what-have-you are invalid, so
// we can't really catch everything here. // we can't really catch everything here.
@ -330,7 +330,7 @@ BOOST_AUTO_TEST_CASE(test_basic_pour_verification)
auto witness = merkleTree.witness(); auto witness = merkleTree.witness();
// create CPourTx // create JSDescription
uint256 pubKeyHash; uint256 pubKeyHash;
boost::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs = { boost::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs = {
libzcash::JSInput(witness, note, k), libzcash::JSInput(witness, note, k),
@ -342,28 +342,28 @@ BOOST_AUTO_TEST_CASE(test_basic_pour_verification)
}; };
{ {
CPourTx pourtx(*p, pubKeyHash, rt, inputs, outputs, 0, 0); JSDescription jsdesc(*p, pubKeyHash, rt, inputs, outputs, 0, 0);
BOOST_CHECK(pourtx.Verify(*p, pubKeyHash)); BOOST_CHECK(jsdesc.Verify(*p, pubKeyHash));
CDataStream ss(SER_DISK, CLIENT_VERSION); CDataStream ss(SER_DISK, CLIENT_VERSION);
ss << pourtx; ss << jsdesc;
CPourTx pourtx_deserialized; JSDescription jsdesc_deserialized;
ss >> pourtx_deserialized; ss >> jsdesc_deserialized;
BOOST_CHECK(pourtx_deserialized == pourtx); BOOST_CHECK(jsdesc_deserialized == jsdesc);
BOOST_CHECK(pourtx_deserialized.Verify(*p, pubKeyHash)); BOOST_CHECK(jsdesc_deserialized.Verify(*p, pubKeyHash));
} }
{ {
// Ensure that the balance equation is working. // Ensure that the balance equation is working.
BOOST_CHECK_THROW(CPourTx(*p, pubKeyHash, rt, inputs, outputs, 10, 0), std::invalid_argument); BOOST_CHECK_THROW(JSDescription(*p, pubKeyHash, rt, inputs, outputs, 10, 0), std::invalid_argument);
BOOST_CHECK_THROW(CPourTx(*p, pubKeyHash, rt, inputs, outputs, 0, 10), std::invalid_argument); BOOST_CHECK_THROW(JSDescription(*p, pubKeyHash, rt, inputs, outputs, 0, 10), std::invalid_argument);
} }
{ {
// Ensure that it won't verify if the root is changed. // Ensure that it won't verify if the root is changed.
auto test = CPourTx(*p, pubKeyHash, rt, inputs, outputs, 0, 0); auto test = JSDescription(*p, pubKeyHash, rt, inputs, outputs, 0, 0);
test.anchor = GetRandHash(); test.anchor = GetRandHash();
BOOST_CHECK(!test.Verify(*p, pubKeyHash)); BOOST_CHECK(!test.Verify(*p, pubKeyHash));
} }
@ -371,20 +371,20 @@ BOOST_AUTO_TEST_CASE(test_basic_pour_verification)
delete p; delete p;
} }
BOOST_AUTO_TEST_CASE(test_simple_pour_invalidity) BOOST_AUTO_TEST_CASE(test_simple_joinsplit_invalidity)
{ {
CMutableTransaction tx; CMutableTransaction tx;
tx.nVersion = 2; tx.nVersion = 2;
{ {
// Ensure that empty vin/vout remain invalid without // Ensure that empty vin/vout remain invalid without
// pours. // joinsplits.
CMutableTransaction newTx(tx); CMutableTransaction newTx(tx);
CValidationState state; CValidationState state;
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
crypto_sign_keypair(newTx.joinSplitPubKey.begin(), joinSplitPrivKey); crypto_sign_keypair(newTx.joinSplitPubKey.begin(), joinSplitPrivKey);
// No pours, vin and vout, means it should be invalid. // No joinsplits, vin and vout, means it should be invalid.
BOOST_CHECK(!CheckTransactionWithoutProofVerification(newTx, state)); BOOST_CHECK(!CheckTransactionWithoutProofVerification(newTx, state));
BOOST_CHECK(state.GetRejectReason() == "bad-txns-vin-empty"); BOOST_CHECK(state.GetRejectReason() == "bad-txns-vin-empty");
@ -393,11 +393,11 @@ BOOST_AUTO_TEST_CASE(test_simple_pour_invalidity)
BOOST_CHECK(!CheckTransactionWithoutProofVerification(newTx, state)); BOOST_CHECK(!CheckTransactionWithoutProofVerification(newTx, state));
BOOST_CHECK(state.GetRejectReason() == "bad-txns-vout-empty"); BOOST_CHECK(state.GetRejectReason() == "bad-txns-vout-empty");
newTx.vpour.push_back(CPourTx()); newTx.vjoinsplit.push_back(JSDescription());
CPourTx *pourtx = &newTx.vpour[0]; JSDescription *jsdesc = &newTx.vjoinsplit[0];
pourtx->serials[0] = GetRandHash(); jsdesc->nullifiers[0] = GetRandHash();
pourtx->serials[1] = GetRandHash(); jsdesc->nullifiers[1] = GetRandHash();
BOOST_CHECK(!CheckTransactionWithoutProofVerification(newTx, state)); BOOST_CHECK(!CheckTransactionWithoutProofVerification(newTx, state));
BOOST_CHECK(state.GetRejectReason() == "bad-txns-invalid-joinsplit-signature"); BOOST_CHECK(state.GetRejectReason() == "bad-txns-invalid-joinsplit-signature");
@ -418,78 +418,78 @@ BOOST_AUTO_TEST_CASE(test_simple_pour_invalidity)
BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state)); BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state));
} }
{ {
// Ensure that values within the pour are well-formed. // Ensure that values within the joinsplit are well-formed.
CMutableTransaction newTx(tx); CMutableTransaction newTx(tx);
CValidationState state; CValidationState state;
newTx.vpour.push_back(CPourTx()); newTx.vjoinsplit.push_back(JSDescription());
CPourTx *pourtx = &newTx.vpour[0]; JSDescription *jsdesc = &newTx.vjoinsplit[0];
pourtx->vpub_old = -1; jsdesc->vpub_old = -1;
BOOST_CHECK(!CheckTransaction(newTx, state)); BOOST_CHECK(!CheckTransaction(newTx, state));
BOOST_CHECK(state.GetRejectReason() == "bad-txns-vpub_old-negative"); BOOST_CHECK(state.GetRejectReason() == "bad-txns-vpub_old-negative");
pourtx->vpub_old = MAX_MONEY + 1; jsdesc->vpub_old = MAX_MONEY + 1;
BOOST_CHECK(!CheckTransaction(newTx, state)); BOOST_CHECK(!CheckTransaction(newTx, state));
BOOST_CHECK(state.GetRejectReason() == "bad-txns-vpub_old-toolarge"); BOOST_CHECK(state.GetRejectReason() == "bad-txns-vpub_old-toolarge");
pourtx->vpub_old = 0; jsdesc->vpub_old = 0;
pourtx->vpub_new = -1; jsdesc->vpub_new = -1;
BOOST_CHECK(!CheckTransaction(newTx, state)); BOOST_CHECK(!CheckTransaction(newTx, state));
BOOST_CHECK(state.GetRejectReason() == "bad-txns-vpub_new-negative"); BOOST_CHECK(state.GetRejectReason() == "bad-txns-vpub_new-negative");
pourtx->vpub_new = MAX_MONEY + 1; jsdesc->vpub_new = MAX_MONEY + 1;
BOOST_CHECK(!CheckTransaction(newTx, state)); BOOST_CHECK(!CheckTransaction(newTx, state));
BOOST_CHECK(state.GetRejectReason() == "bad-txns-vpub_new-toolarge"); BOOST_CHECK(state.GetRejectReason() == "bad-txns-vpub_new-toolarge");
pourtx->vpub_new = (MAX_MONEY / 2) + 10; jsdesc->vpub_new = (MAX_MONEY / 2) + 10;
newTx.vpour.push_back(CPourTx()); newTx.vjoinsplit.push_back(JSDescription());
CPourTx *pourtx2 = &newTx.vpour[1]; JSDescription *jsdesc2 = &newTx.vjoinsplit[1];
pourtx2->vpub_new = (MAX_MONEY / 2) + 10; jsdesc2->vpub_new = (MAX_MONEY / 2) + 10;
BOOST_CHECK(!CheckTransaction(newTx, state)); BOOST_CHECK(!CheckTransaction(newTx, state));
BOOST_CHECK(state.GetRejectReason() == "bad-txns-txouttotal-toolarge"); BOOST_CHECK(state.GetRejectReason() == "bad-txns-txouttotal-toolarge");
} }
{ {
// Ensure that serials are never duplicated within a transaction. // Ensure that nullifiers are never duplicated within a transaction.
CMutableTransaction newTx(tx); CMutableTransaction newTx(tx);
CValidationState state; CValidationState state;
newTx.vpour.push_back(CPourTx()); newTx.vjoinsplit.push_back(JSDescription());
CPourTx *pourtx = &newTx.vpour[0]; JSDescription *jsdesc = &newTx.vjoinsplit[0];
pourtx->serials[0] = GetRandHash(); jsdesc->nullifiers[0] = GetRandHash();
pourtx->serials[1] = pourtx->serials[0]; jsdesc->nullifiers[1] = jsdesc->nullifiers[0];
BOOST_CHECK(!CheckTransaction(newTx, state)); BOOST_CHECK(!CheckTransaction(newTx, state));
BOOST_CHECK(state.GetRejectReason() == "bad-pours-serials-duplicate"); BOOST_CHECK(state.GetRejectReason() == "bad-joinsplits-nullifiers-duplicate");
pourtx->serials[1] = GetRandHash(); jsdesc->nullifiers[1] = GetRandHash();
newTx.vpour.push_back(CPourTx()); newTx.vjoinsplit.push_back(JSDescription());
CPourTx *pourtx2 = &newTx.vpour[1]; JSDescription *jsdesc2 = &newTx.vjoinsplit[1];
pourtx2->serials[0] = GetRandHash(); jsdesc2->nullifiers[0] = GetRandHash();
pourtx2->serials[1] = pourtx->serials[0]; jsdesc2->nullifiers[1] = jsdesc->nullifiers[0];
BOOST_CHECK(!CheckTransaction(newTx, state)); BOOST_CHECK(!CheckTransaction(newTx, state));
BOOST_CHECK(state.GetRejectReason() == "bad-pours-serials-duplicate"); BOOST_CHECK(state.GetRejectReason() == "bad-joinsplits-nullifiers-duplicate");
} }
{ {
// Ensure that coinbase transactions do not have pours. // Ensure that coinbase transactions do not have joinsplits.
CMutableTransaction newTx(tx); CMutableTransaction newTx(tx);
CValidationState state; CValidationState state;
newTx.vpour.push_back(CPourTx()); newTx.vjoinsplit.push_back(JSDescription());
CPourTx *pourtx = &newTx.vpour[0]; JSDescription *jsdesc = &newTx.vjoinsplit[0];
pourtx->serials[0] = GetRandHash(); jsdesc->nullifiers[0] = GetRandHash();
pourtx->serials[1] = GetRandHash(); jsdesc->nullifiers[1] = GetRandHash();
newTx.vin.push_back(CTxIn(uint256(), -1)); newTx.vin.push_back(CTxIn(uint256(), -1));
@ -498,7 +498,7 @@ BOOST_AUTO_TEST_CASE(test_simple_pour_invalidity)
BOOST_CHECK(finalNewTx.IsCoinBase()); BOOST_CHECK(finalNewTx.IsCoinBase());
} }
BOOST_CHECK(!CheckTransaction(newTx, state)); BOOST_CHECK(!CheckTransaction(newTx, state));
BOOST_CHECK(state.GetRejectReason() == "bad-cb-has-pours"); BOOST_CHECK(state.GetRejectReason() == "bad-cb-has-joinsplits");
} }
} }

View File

@ -18,7 +18,7 @@
using namespace std; using namespace std;
static const char DB_ANCHOR = 'A'; static const char DB_ANCHOR = 'A';
static const char DB_SERIAL = 's'; static const char DB_NULLIFIER = 's';
static const char DB_COINS = 'c'; static const char DB_COINS = 'c';
static const char DB_BLOCK_FILES = 'f'; static const char DB_BLOCK_FILES = 'f';
static const char DB_TXINDEX = 't'; static const char DB_TXINDEX = 't';
@ -43,11 +43,11 @@ void static BatchWriteAnchor(CLevelDBBatch &batch,
} }
} }
void static BatchWriteSerial(CLevelDBBatch &batch, const uint256 &serial, const bool &entered) { void static BatchWriteNullifier(CLevelDBBatch &batch, const uint256 &nf, const bool &entered) {
if (!entered) if (!entered)
batch.Erase(make_pair(DB_SERIAL, serial)); batch.Erase(make_pair(DB_NULLIFIER, nf));
else else
batch.Write(make_pair(DB_SERIAL, serial), true); batch.Write(make_pair(DB_NULLIFIER, nf), true);
} }
void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) { void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) {
@ -81,9 +81,9 @@ bool CCoinsViewDB::GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree)
return read; return read;
} }
bool CCoinsViewDB::GetSerial(const uint256 &serial) const { bool CCoinsViewDB::GetNullifier(const uint256 &nf) const {
bool spent = false; bool spent = false;
bool read = db.Read(make_pair(DB_SERIAL, serial), spent); bool read = db.Read(make_pair(DB_NULLIFIER, nf), spent);
return read; return read;
} }
@ -114,7 +114,7 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins,
const uint256 &hashBlock, const uint256 &hashBlock,
const uint256 &hashAnchor, const uint256 &hashAnchor,
CAnchorsMap &mapAnchors, CAnchorsMap &mapAnchors,
CSerialsMap &mapSerials) { CNullifiersMap &mapNullifiers) {
CLevelDBBatch batch; CLevelDBBatch batch;
size_t count = 0; size_t count = 0;
size_t changed = 0; size_t changed = 0;
@ -137,13 +137,13 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins,
mapAnchors.erase(itOld); mapAnchors.erase(itOld);
} }
for (CSerialsMap::iterator it = mapSerials.begin(); it != mapSerials.end();) { for (CNullifiersMap::iterator it = mapNullifiers.begin(); it != mapNullifiers.end();) {
if (it->second.flags & CSerialsCacheEntry::DIRTY) { if (it->second.flags & CNullifiersCacheEntry::DIRTY) {
BatchWriteSerial(batch, it->first, it->second.entered); BatchWriteNullifier(batch, it->first, it->second.entered);
// TODO: changed++? // TODO: changed++?
} }
CSerialsMap::iterator itOld = it++; CNullifiersMap::iterator itOld = it++;
mapSerials.erase(itOld); mapNullifiers.erase(itOld);
} }
if (!hashBlock.IsNull()) if (!hashBlock.IsNull())

View File

@ -35,7 +35,7 @@ public:
CCoinsViewDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false); CCoinsViewDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const; bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const;
bool GetSerial(const uint256 &serial) const; bool GetNullifier(const uint256 &nf) const;
bool GetCoins(const uint256 &txid, CCoins &coins) const; bool GetCoins(const uint256 &txid, CCoins &coins) const;
bool HaveCoins(const uint256 &txid) const; bool HaveCoins(const uint256 &txid) const;
uint256 GetBestBlock() const; uint256 GetBestBlock() const;
@ -44,7 +44,7 @@ public:
const uint256 &hashBlock, const uint256 &hashBlock,
const uint256 &hashAnchor, const uint256 &hashAnchor,
CAnchorsMap &mapAnchors, CAnchorsMap &mapAnchors,
CSerialsMap &mapSerials); CNullifiersMap &mapNullifiers);
bool GetStats(CCoinsStats &stats) const; bool GetStats(CCoinsStats &stats) const;
}; };

View File

@ -99,9 +99,9 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
const CTransaction& tx = mapTx[hash].GetTx(); const CTransaction& tx = mapTx[hash].GetTx();
for (unsigned int i = 0; i < tx.vin.size(); i++) for (unsigned int i = 0; i < tx.vin.size(); i++)
mapNextTx[tx.vin[i].prevout] = CInPoint(&tx, i); mapNextTx[tx.vin[i].prevout] = CInPoint(&tx, i);
BOOST_FOREACH(const CPourTx &pour, tx.vpour) { BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
BOOST_FOREACH(const uint256 &serial, pour.serials) { BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) {
mapSerials[serial] = &tx; mapNullifiers[nf] = &tx;
} }
} }
nTransactionsUpdated++; nTransactionsUpdated++;
@ -148,9 +148,9 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list<CTransaction>& rem
} }
BOOST_FOREACH(const CTxIn& txin, tx.vin) BOOST_FOREACH(const CTxIn& txin, tx.vin)
mapNextTx.erase(txin.prevout); mapNextTx.erase(txin.prevout);
BOOST_FOREACH(const CPourTx& pour, tx.vpour) { BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) {
BOOST_FOREACH(const uint256& serial, pour.serials) { BOOST_FOREACH(const uint256& nf, joinsplit.nullifiers) {
mapSerials.erase(serial); mapNullifiers.erase(nf);
} }
} }
@ -200,8 +200,8 @@ void CTxMemPool::removeWithAnchor(const uint256 &invalidRoot)
for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) { for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
const CTransaction& tx = it->second.GetTx(); const CTransaction& tx = it->second.GetTx();
BOOST_FOREACH(const CPourTx& pour, tx.vpour) { BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) {
if (pour.anchor == invalidRoot) { if (joinsplit.anchor == invalidRoot) {
transactionsToRemove.push_back(tx); transactionsToRemove.push_back(tx);
break; break;
} }
@ -230,10 +230,10 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>
} }
} }
BOOST_FOREACH(const CPourTx &pour, tx.vpour) { BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
BOOST_FOREACH(const uint256 &serial, pour.serials) { BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) {
std::map<uint256, const CTransaction*>::iterator it = mapSerials.find(serial); std::map<uint256, const CTransaction*>::iterator it = mapNullifiers.find(nf);
if (it != mapSerials.end()) { if (it != mapNullifiers.end()) {
const CTransaction &txConflict = *it->second; const CTransaction &txConflict = *it->second;
if (txConflict != tx) if (txConflict != tx)
{ {
@ -317,20 +317,20 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
boost::unordered_map<uint256, ZCIncrementalMerkleTree, CCoinsKeyHasher> intermediates; boost::unordered_map<uint256, ZCIncrementalMerkleTree, CCoinsKeyHasher> intermediates;
BOOST_FOREACH(const CPourTx &pour, tx.vpour) { BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
BOOST_FOREACH(const uint256 &serial, pour.serials) { BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) {
assert(!pcoins->GetSerial(serial)); assert(!pcoins->GetNullifier(nf));
} }
ZCIncrementalMerkleTree tree; ZCIncrementalMerkleTree tree;
auto it = intermediates.find(pour.anchor); auto it = intermediates.find(joinsplit.anchor);
if (it != intermediates.end()) { if (it != intermediates.end()) {
tree = it->second; tree = it->second;
} else { } else {
assert(pcoins->GetAnchorAt(pour.anchor, tree)); assert(pcoins->GetAnchorAt(joinsplit.anchor, tree));
} }
BOOST_FOREACH(const uint256& commitment, pour.commitments) BOOST_FOREACH(const uint256& commitment, joinsplit.commitments)
{ {
tree.append(commitment); tree.append(commitment);
} }
@ -370,7 +370,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
assert(it->first == it->second.ptx->vin[it->second.n].prevout); assert(it->first == it->second.ptx->vin[it->second.n].prevout);
} }
for (std::map<uint256, const CTransaction*>::const_iterator it = mapSerials.begin(); it != mapSerials.end(); it++) { for (std::map<uint256, const CTransaction*>::const_iterator it = mapNullifiers.begin(); it != mapNullifiers.end(); it++) {
uint256 hash = it->second->GetHash(); uint256 hash = it->second->GetHash();
map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(hash); map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(hash);
const CTransaction& tx = it2->second.GetTx(); const CTransaction& tx = it2->second.GetTx();
@ -484,11 +484,11 @@ bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const
CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { } CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { }
bool CCoinsViewMemPool::GetSerial(const uint256 &serial) const { bool CCoinsViewMemPool::GetNullifier(const uint256 &nf) const {
if (mempool.mapSerials.count(serial)) if (mempool.mapNullifiers.count(nf))
return true; return true;
return base->GetSerial(serial); return base->GetNullifier(nf);
} }
bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) const { bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) const {

View File

@ -98,7 +98,7 @@ public:
mutable CCriticalSection cs; mutable CCriticalSection cs;
std::map<uint256, CTxMemPoolEntry> mapTx; std::map<uint256, CTxMemPoolEntry> mapTx;
std::map<COutPoint, CInPoint> mapNextTx; std::map<COutPoint, CInPoint> mapNextTx;
std::map<uint256, const CTransaction*> mapSerials; std::map<uint256, const CTransaction*> mapNullifiers;
std::map<uint256, std::pair<double, CAmount> > mapDeltas; std::map<uint256, std::pair<double, CAmount> > mapDeltas;
CTxMemPool(const CFeeRate& _minRelayFee); CTxMemPool(const CFeeRate& _minRelayFee);
@ -177,7 +177,7 @@ protected:
public: public:
CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn); CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn);
bool GetSerial(const uint256 &txid) const; bool GetNullifier(const uint256 &txid) const;
bool GetCoins(const uint256 &txid, CCoins &coins) const; bool GetCoins(const uint256 &txid, CCoins &coins) const;
bool HaveCoins(const uint256 &txid) const; bool HaveCoins(const uint256 &txid) const;
}; };

View File

@ -2393,18 +2393,18 @@ Value zc_benchmark(const json_spirit::Array& params, bool fHelp)
pzcashParams->loadProvingKey(); pzcashParams->loadProvingKey();
} }
CPourTx* samplejoinsplit = NULL; JSDescription* samplejoinsplit = NULL;
if (benchmarktype == "verifyjoinsplit") { if (benchmarktype == "verifyjoinsplit") {
uint256 pubKeyHash; uint256 pubKeyHash;
uint256 anchor = ZCIncrementalMerkleTree().root(); uint256 anchor = ZCIncrementalMerkleTree().root();
samplejoinsplit = new CPourTx(*pzcashParams, samplejoinsplit = new JSDescription(*pzcashParams,
pubKeyHash, pubKeyHash,
anchor, anchor,
{JSInput(), JSInput()}, {JSInput(), JSInput()},
{JSOutput(), JSOutput()}, {JSOutput(), JSOutput()},
0, 0,
0); 0);
} }
for (int i = 0; i < samplecount; i++) { for (int i = 0; i < samplecount; i++) {
@ -2448,14 +2448,14 @@ Value zc_raw_receive(const json_spirit::Array& params, bool fHelp)
if (fHelp || params.size() != 2) { if (fHelp || params.size() != 2) {
throw runtime_error( throw runtime_error(
"zcrawreceive zcsecretkey encryptedbucket\n" "zcrawreceive zcsecretkey encryptednote\n"
"\n" "\n"
"Decrypts encryptedbucket and checks if the coin commitments\n" "Decrypts encryptednote and checks if the coin commitments\n"
"are in the blockchain as indicated by the \"exists\" result.\n" "are in the blockchain as indicated by the \"exists\" result.\n"
"\n" "\n"
"Output: {\n" "Output: {\n"
" \"amount\": value,\n" " \"amount\": value,\n"
" \"bucket\": cleartextbucket,\n" " \"note\": noteplaintext,\n"
" \"exists\": exists\n" " \"exists\": exists\n"
"}\n" "}\n"
); );
@ -2474,7 +2474,7 @@ Value zc_raw_receive(const json_spirit::Array& params, bool fHelp)
uint256 h_sig; uint256 h_sig;
{ {
CDataStream ssData(ParseHexV(params[1], "encrypted_bucket"), SER_NETWORK, PROTOCOL_VERSION); CDataStream ssData(ParseHexV(params[1], "encrypted_note"), SER_NETWORK, PROTOCOL_VERSION);
try { try {
ssData >> nonce; ssData >> nonce;
ssData >> epk; ssData >> epk;
@ -2482,7 +2482,7 @@ Value zc_raw_receive(const json_spirit::Array& params, bool fHelp)
ssData >> h_sig; ssData >> h_sig;
} catch(const std::exception &) { } catch(const std::exception &) {
throw runtime_error( throw runtime_error(
"encrypted_bucket could not be decoded" "encrypted_note could not be decoded"
); );
} }
} }
@ -2503,7 +2503,7 @@ Value zc_raw_receive(const json_spirit::Array& params, bool fHelp)
std::vector<boost::optional<ZCIncrementalWitness>> witnesses; std::vector<boost::optional<ZCIncrementalWitness>> witnesses;
uint256 anchor; uint256 anchor;
uint256 commitment = decrypted_note.cm(); uint256 commitment = decrypted_note.cm();
pwalletMain->WitnessBucketCommitment( pwalletMain->WitnessNoteCommitment(
{commitment}, {commitment},
witnesses, witnesses,
anchor anchor
@ -2514,14 +2514,14 @@ Value zc_raw_receive(const json_spirit::Array& params, bool fHelp)
Object result; Object result;
result.push_back(Pair("amount", ValueFromAmount(decrypted_note.value))); result.push_back(Pair("amount", ValueFromAmount(decrypted_note.value)));
result.push_back(Pair("bucket", HexStr(ss.begin(), ss.end()))); result.push_back(Pair("note", HexStr(ss.begin(), ss.end())));
result.push_back(Pair("exists", (bool) witnesses[0])); result.push_back(Pair("exists", (bool) witnesses[0]));
return result; return result;
} }
Value zc_raw_pour(const json_spirit::Array& params, bool fHelp) Value zc_raw_joinsplit(const json_spirit::Array& params, bool fHelp)
{ {
if (!EnsureWalletIsAvailable(fHelp)) { if (!EnsureWalletIsAvailable(fHelp)) {
return Value::null; return Value::null;
@ -2529,11 +2529,11 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
if (fHelp || params.size() != 5) { if (fHelp || params.size() != 5) {
throw runtime_error( throw runtime_error(
"zcrawpour rawtx inputs outputs vpub_old vpub_new\n" "zcrawjoinsplit rawtx inputs outputs vpub_old vpub_new\n"
" inputs: a JSON object mapping {bucket: zcsecretkey, ...}\n" " inputs: a JSON object mapping {note: zcsecretkey, ...}\n"
" outputs: a JSON object mapping {zcaddr: value, ...}\n" " outputs: a JSON object mapping {zcaddr: value, ...}\n"
"\n" "\n"
"Splices a Pour into rawtx. Inputs are unilaterally confidential.\n" "Splices a joinsplit into rawtx. Inputs are unilaterally confidential.\n"
"Outputs are confidential between sender/receiver. The vpub_old and\n" "Outputs are confidential between sender/receiver. The vpub_old and\n"
"vpub_new values are globally public and move transparent value into\n" "vpub_new values are globally public and move transparent value into\n"
"or out of the confidential value store, respectively.\n" "or out of the confidential value store, respectively.\n"
@ -2544,8 +2544,8 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
"payments in-band on the blockchain.)\n" "payments in-band on the blockchain.)\n"
"\n" "\n"
"Output: {\n" "Output: {\n"
" \"encryptedbucket1\": enc1,\n" " \"encryptednote1\": enc1,\n"
" \"encryptedbucket2\": enc2,\n" " \"encryptednote2\": enc2,\n"
" \"rawtxn\": rawtxout\n" " \"rawtxn\": rawtxout\n"
"}\n" "}\n"
); );
@ -2569,8 +2569,8 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
if (params[4].get_real() != 0.0) if (params[4].get_real() != 0.0)
vpub_new = AmountFromValue(params[4]); vpub_new = AmountFromValue(params[4]);
std::vector<JSInput> vpourin; std::vector<JSInput> vjsin;
std::vector<JSOutput> vpourout; std::vector<JSOutput> vjsout;
std::vector<Note> notes; std::vector<Note> notes;
std::vector<SpendingKey> keys; std::vector<SpendingKey> keys;
std::vector<uint256> commitments; std::vector<uint256> commitments;
@ -2585,7 +2585,7 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
NotePlaintext npt; NotePlaintext npt;
{ {
CDataStream ssData(ParseHexV(s.name_, "bucket"), SER_NETWORK, PROTOCOL_VERSION); CDataStream ssData(ParseHexV(s.name_, "note"), SER_NETWORK, PROTOCOL_VERSION);
ssData >> npt; ssData >> npt;
} }
@ -2597,7 +2597,7 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
uint256 anchor; uint256 anchor;
std::vector<boost::optional<ZCIncrementalWitness>> witnesses; std::vector<boost::optional<ZCIncrementalWitness>> witnesses;
pwalletMain->WitnessBucketCommitment(commitments, witnesses, anchor); pwalletMain->WitnessNoteCommitment(commitments, witnesses, anchor);
assert(witnesses.size() == notes.size()); assert(witnesses.size() == notes.size());
assert(notes.size() == keys.size()); assert(notes.size() == keys.size());
@ -2606,16 +2606,16 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
for (size_t i = 0; i < witnesses.size(); i++) { for (size_t i = 0; i < witnesses.size(); i++) {
if (!witnesses[i]) { if (!witnesses[i]) {
throw runtime_error( throw runtime_error(
"pour input could not be found in tree" "joinsplit input could not be found in tree"
); );
} }
vpourin.push_back(JSInput(*witnesses[i], notes[i], keys[i])); vjsin.push_back(JSInput(*witnesses[i], notes[i], keys[i]));
} }
} }
while (vpourin.size() < ZC_NUM_JS_INPUTS) { while (vjsin.size() < ZC_NUM_JS_INPUTS) {
vpourin.push_back(JSInput()); vjsin.push_back(JSInput());
} }
BOOST_FOREACH(const Pair& s, outputs) BOOST_FOREACH(const Pair& s, outputs)
@ -2624,16 +2624,16 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
PaymentAddress addrTo = pubaddr.Get(); PaymentAddress addrTo = pubaddr.Get();
CAmount nAmount = AmountFromValue(s.value_); CAmount nAmount = AmountFromValue(s.value_);
vpourout.push_back(JSOutput(addrTo, nAmount)); vjsout.push_back(JSOutput(addrTo, nAmount));
} }
while (vpourout.size() < ZC_NUM_JS_OUTPUTS) { while (vjsout.size() < ZC_NUM_JS_OUTPUTS) {
vpourout.push_back(JSOutput()); vjsout.push_back(JSOutput());
} }
// TODO // TODO
if (vpourout.size() != ZC_NUM_JS_INPUTS || vpourin.size() != ZC_NUM_JS_OUTPUTS) { if (vjsout.size() != ZC_NUM_JS_INPUTS || vjsin.size() != ZC_NUM_JS_OUTPUTS) {
throw runtime_error("unsupported pour input/output counts"); throw runtime_error("unsupported joinsplit input/output counts");
} }
uint256 joinSplitPubKey; uint256 joinSplitPubKey;
@ -2644,17 +2644,17 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
mtx.nVersion = 2; mtx.nVersion = 2;
mtx.joinSplitPubKey = joinSplitPubKey; mtx.joinSplitPubKey = joinSplitPubKey;
CPourTx pourtx(*pzcashParams, JSDescription jsdesc(*pzcashParams,
joinSplitPubKey, joinSplitPubKey,
anchor, anchor,
{vpourin[0], vpourin[1]}, {vjsin[0], vjsin[1]},
{vpourout[0], vpourout[1]}, {vjsout[0], vjsout[1]},
vpub_old, vpub_old,
vpub_new); vpub_new);
assert(pourtx.Verify(*pzcashParams, joinSplitPubKey)); assert(jsdesc.Verify(*pzcashParams, joinSplitPubKey));
mtx.vpour.push_back(pourtx); mtx.vjoinsplit.push_back(jsdesc);
// TODO: #966. // TODO: #966.
static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
@ -2683,30 +2683,30 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << rawTx; ss << rawTx;
std::string encryptedBucket1; std::string encryptedNote1;
std::string encryptedBucket2; std::string encryptedNote2;
{ {
CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
ss2 << ((unsigned char) 0x00); ss2 << ((unsigned char) 0x00);
ss2 << pourtx.ephemeralKey; ss2 << jsdesc.ephemeralKey;
ss2 << pourtx.ciphertexts[0]; ss2 << jsdesc.ciphertexts[0];
ss2 << pourtx.h_sig(*pzcashParams, joinSplitPubKey); ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey);
encryptedBucket1 = HexStr(ss2.begin(), ss2.end()); encryptedNote1 = HexStr(ss2.begin(), ss2.end());
} }
{ {
CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
ss2 << ((unsigned char) 0x01); ss2 << ((unsigned char) 0x01);
ss2 << pourtx.ephemeralKey; ss2 << jsdesc.ephemeralKey;
ss2 << pourtx.ciphertexts[1]; ss2 << jsdesc.ciphertexts[1];
ss2 << pourtx.h_sig(*pzcashParams, joinSplitPubKey); ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey);
encryptedBucket2 = HexStr(ss2.begin(), ss2.end()); encryptedNote2 = HexStr(ss2.begin(), ss2.end());
} }
Object result; Object result;
result.push_back(Pair("encryptedbucket1", encryptedBucket1)); result.push_back(Pair("encryptednote1", encryptedNote1));
result.push_back(Pair("encryptedbucket2", encryptedBucket2)); result.push_back(Pair("encryptednote2", encryptedNote2));
result.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end()))); result.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end())));
return result; return result;
} }

View File

@ -1051,9 +1051,9 @@ bool CWalletTx::WriteToDisk(CWalletDB *pwalletdb)
return pwalletdb->WriteTx(GetHash(), *this); return pwalletdb->WriteTx(GetHash(), *this);
} }
void CWallet::WitnessBucketCommitment(std::vector<uint256> commitments, void CWallet::WitnessNoteCommitment(std::vector<uint256> commitments,
std::vector<boost::optional<ZCIncrementalWitness>>& witnesses, std::vector<boost::optional<ZCIncrementalWitness>>& witnesses,
uint256 &final_anchor) uint256 &final_anchor)
{ {
witnesses.resize(commitments.size()); witnesses.resize(commitments.size());
CBlockIndex* pindex = chainActive.Genesis(); CBlockIndex* pindex = chainActive.Genesis();
@ -1065,21 +1065,21 @@ void CWallet::WitnessBucketCommitment(std::vector<uint256> commitments,
BOOST_FOREACH(const CTransaction& tx, block.vtx) BOOST_FOREACH(const CTransaction& tx, block.vtx)
{ {
BOOST_FOREACH(const CPourTx& pour, tx.vpour) BOOST_FOREACH(const JSDescription& jsdesc, tx.vjoinsplit)
{ {
BOOST_FOREACH(const uint256 &bucket_commitment, pour.commitments) BOOST_FOREACH(const uint256 &note_commitment, jsdesc.commitments)
{ {
tree.append(bucket_commitment); tree.append(note_commitment);
BOOST_FOREACH(boost::optional<ZCIncrementalWitness>& wit, witnesses) { BOOST_FOREACH(boost::optional<ZCIncrementalWitness>& wit, witnesses) {
if (wit) { if (wit) {
wit->append(bucket_commitment); wit->append(note_commitment);
} }
} }
size_t i = 0; size_t i = 0;
BOOST_FOREACH(uint256& commitment, commitments) { BOOST_FOREACH(uint256& commitment, commitments) {
if (bucket_commitment == commitment) { if (note_commitment == commitment) {
witnesses.at(i) = tree.witness(); witnesses.at(i) = tree.witness();
} }
i++; i++;

View File

@ -616,7 +616,7 @@ public:
void SyncTransaction(const CTransaction& tx, const CBlock* pblock); void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate); bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate);
void EraseFromWallet(const uint256 &hash); void EraseFromWallet(const uint256 &hash);
void WitnessBucketCommitment( void WitnessNoteCommitment(
std::vector<uint256> commitments, std::vector<uint256> commitments,
std::vector<boost::optional<ZCIncrementalWitness>>& witnesses, std::vector<boost::optional<ZCIncrementalWitness>>& witnesses,
uint256 &final_anchor); uint256 &final_anchor);

View File

@ -76,20 +76,20 @@ double benchmark_create_joinsplit()
uint256 anchor = ZCIncrementalMerkleTree().root(); uint256 anchor = ZCIncrementalMerkleTree().root();
timer_start(); timer_start();
CPourTx pourtx(*pzcashParams, JSDescription jsdesc(*pzcashParams,
pubKeyHash, pubKeyHash,
anchor, anchor,
{JSInput(), JSInput()}, {JSInput(), JSInput()},
{JSOutput(), JSOutput()}, {JSOutput(), JSOutput()},
0, 0,
0); 0);
double ret = timer_stop(); double ret = timer_stop();
assert(pourtx.Verify(*pzcashParams, pubKeyHash)); assert(jsdesc.Verify(*pzcashParams, pubKeyHash));
return ret; return ret;
} }
double benchmark_verify_joinsplit(const CPourTx &joinsplit) double benchmark_verify_joinsplit(const JSDescription &joinsplit)
{ {
timer_start(); timer_start();
uint256 pubKeyHash; uint256 pubKeyHash;

View File

@ -8,7 +8,7 @@ extern double benchmark_sleep();
extern double benchmark_parameter_loading(); extern double benchmark_parameter_loading();
extern double benchmark_create_joinsplit(); extern double benchmark_create_joinsplit();
extern double benchmark_solve_equihash(); extern double benchmark_solve_equihash();
extern double benchmark_verify_joinsplit(const CPourTx &joinsplit); extern double benchmark_verify_joinsplit(const JSDescription &joinsplit);
extern double benchmark_verify_equihash(); extern double benchmark_verify_equihash();
extern double benchmark_large_tx(); extern double benchmark_large_tx();