Auto merge of #1911 - bitcartel:1823_witness_does_not_have_same_anchor_as_change_input, r=str4d
With chained joinsplits, witness anchors for input notes no longer cross block boundaries Closes #1823
This commit is contained in:
@@ -323,7 +323,22 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
zOutputsDeque.push_back(o);
|
||||
}
|
||||
|
||||
|
||||
// When spending notes, take a snapshot of note witnesses and anchors as the treestate will
|
||||
// change upon arrival of new blocks which contain joinsplit transactions. This is likely
|
||||
// to happen as creating a chained joinsplit transaction can take longer than the block interval.
|
||||
if (z_inputs_.size() > 0) {
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
for (auto t : z_inputs_) {
|
||||
JSOutPoint jso = std::get<0>(t);
|
||||
std::vector<JSOutPoint> vOutPoints = { jso };
|
||||
uint256 inputAnchor;
|
||||
std::vector<boost::optional<ZCIncrementalWitness>> vInputWitnesses;
|
||||
pwalletMain->GetNoteWitnesses(vOutPoints, vInputWitnesses, inputAnchor);
|
||||
jsopWitnessAnchorMap[ jso.ToString() ] = WitnessAnchorData{ vInputWitnesses[0], inputAnchor };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* SCENARIO #2
|
||||
*
|
||||
@@ -573,6 +588,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
//
|
||||
std::vector<Note> vInputNotes;
|
||||
std::vector<JSOutPoint> vOutPoints;
|
||||
std::vector<boost::optional<ZCIncrementalWitness>> vInputWitnesses;
|
||||
uint256 inputAnchor;
|
||||
int numInputsNeeded = (jsChange>0) ? 1 : 0;
|
||||
while (numInputsNeeded++ < ZC_NUM_JS_INPUTS && zInputsDeque.size() > 0) {
|
||||
@@ -582,6 +598,14 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
CAmount noteFunds = std::get<2>(t);
|
||||
zInputsDeque.pop_front();
|
||||
|
||||
WitnessAnchorData wad = jsopWitnessAnchorMap[ jso.ToString() ];
|
||||
vInputWitnesses.push_back(wad.witness);
|
||||
if (inputAnchor.IsNull()) {
|
||||
inputAnchor = wad.anchor;
|
||||
} else if (inputAnchor != wad.anchor) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Selected input notes do not share the same anchor");
|
||||
}
|
||||
|
||||
vOutPoints.push_back(jso);
|
||||
vInputNotes.push_back(note);
|
||||
|
||||
@@ -598,12 +622,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
|
||||
// Add history of previous commitments to witness
|
||||
if (vInputNotes.size() > 0) {
|
||||
std::vector<boost::optional<ZCIncrementalWitness>> vInputWitnesses;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
pwalletMain->GetNoteWitnesses(vOutPoints, vInputWitnesses, inputAnchor);
|
||||
}
|
||||
|
||||
|
||||
if (vInputWitnesses.size()==0) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Could not find witness for note commitment");
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "json/json_spirit_value.h"
|
||||
#include "wallet.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <tuple>
|
||||
|
||||
// Default transaction fee if caller does not specify one.
|
||||
@@ -41,6 +42,12 @@ struct AsyncJoinSplitInfo
|
||||
CAmount vpub_new = 0;
|
||||
};
|
||||
|
||||
// A struct to help us track the witness and anchor for a given JSOutPoint
|
||||
struct WitnessAnchorData {
|
||||
boost::optional<ZCIncrementalWitness> witness;
|
||||
uint256 anchor;
|
||||
};
|
||||
|
||||
class AsyncRPCOperation_sendmany : public AsyncRPCOperation {
|
||||
public:
|
||||
AsyncRPCOperation_sendmany(std::string fromAddress, std::vector<SendManyRecipient> tOutputs, std::vector<SendManyRecipient> zOutputs, int minDepth, CAmount fee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE);
|
||||
@@ -71,7 +78,9 @@ private:
|
||||
uint256 joinSplitPubKey_;
|
||||
unsigned char joinSplitPrivKey_[crypto_sign_SECRETKEYBYTES];
|
||||
|
||||
|
||||
// The key is the result string from calling JSOutPoint::ToString()
|
||||
std::unordered_map<std::string, WitnessAnchorData> jsopWitnessAnchorMap;
|
||||
|
||||
std::vector<SendManyRecipient> t_outputs_;
|
||||
std::vector<SendManyRecipient> z_outputs_;
|
||||
std::vector<SendManyInputUTXO> t_inputs_;
|
||||
|
||||
Reference in New Issue
Block a user