Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Redesign PSET #900

Merged
merged 91 commits into from
Jul 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
fdf71de
Remove PSET and disable PSBT/PSET things for now
achow101 Mar 3, 2021
e882a3a
Types are compact size uints
achow101 Oct 2, 2019
50c281f
Implement PSBT versions
achow101 Oct 2, 2019
ad2b2d7
Add GetVersion helper to PSBT
achow101 Jan 4, 2021
25c13ad
Output psbt version in decodepsbt
achow101 Jan 25, 2021
575fec0
Implement PSBT proprietary type
achow101 Oct 2, 2019
5bb930e
Output proprietary type info in decodepsbt
achow101 Oct 2, 2019
31a7e0a
Test for proprietary field
achow101 Oct 2, 2019
fad29ba
moveonly: Move (Un)Serialize(To/From)Vector, (De)SerializeHDKeypaths …
achow101 Jul 25, 2019
cb9c553
Store version bytes and be able to serialize them in CExtPubKey
achow101 Jul 25, 2019
4eabba9
Separate individual HD Keypath serialization into separate functions
achow101 Jul 25, 2019
5b5c5ef
Implement operator< for KeyOriginInfo and CExtPubKey
achow101 Jul 25, 2019
2c54175
Implement serializations for PSBT_GLOBAL_XPUB
achow101 Jul 25, 2019
7fd50b2
Add global_xpubs to decodepsbt
achow101 Jul 25, 2019
bc2651d
Add global xpub test vectors from BIP
achow101 Jul 25, 2019
20e8dff
Merge global xpubs in joinpsbts and combinepsbts
achow101 Jul 31, 2019
ec03f83
Define psbtv2 field numbers
achow101 Jan 4, 2021
dd792ce
Implement PSBTv2 fields de/ser
achow101 Jan 4, 2021
8c62443
Change PSBT unknown fields test to use higher numbers
achow101 Jan 4, 2021
2042765
Have PSBTInput and PSBTOutput know the PSBT's version
achow101 Jan 4, 2021
457b6bd
Enforce PSBT version constraints
achow101 Jan 4, 2021
c32950e
Add PSBT::CacheUnsignedTxPieces
achow101 Jan 11, 2021
32234df
Call CacheUnsignedTxPieces in PSBT constructor
achow101 Jan 11, 2021
4b805fd
Convert PSBTv0 unsigned tx to PSBTv2 fields
achow101 Jan 11, 2021
3c647b7
Replace PSBT::GetInputUTXO with PSBTInput::GetUTXO
achow101 Jan 11, 2021
10bf247
Add PSBT::ComputeLockTime()
achow101 Jan 11, 2021
32bdf2d
Add PSBT::GetUnsignedTx
achow101 Jan 11, 2021
bd1a57b
Add PSBT::GetUniqueID
achow101 Jan 11, 2021
90cd7ec
Change PSBT::AddInput to take just PSBTInput
achow101 Jan 11, 2021
cd5515a
Change PSBT::AddOutput to take just PSBTOutput
achow101 Jan 11, 2021
4ff2593
Implement PSBTv2 field merging
achow101 Jan 11, 2021
d8dba33
Add PSBTInput::GetOutPoint
achow101 Jan 11, 2021
23f6442
Update SignPSBTInput for PSBTv2
achow101 Jan 11, 2021
f269d11
Update FinalizeAndExtract for v2
achow101 Jan 11, 2021
500554a
Update AnalyzePSBT for PSBTv2
achow101 Jan 11, 2021
c9c23ca
Update PSBT Operations Dialog for v2
achow101 Jan 11, 2021
9c83300
Update RPCs for PSBTv2
achow101 Jan 11, 2021
16395c1
Update wallet for PSBTv2
achow101 Jan 11, 2021
139ac36
Implement PSBTv2 AddInput and AddOutput
achow101 Jan 18, 2021
bedc1e0
Implement PSBTv2 in decodepsbt
achow101 Jan 18, 2021
a34474e
Allow specifying PSBT version in constructor
achow101 Jan 18, 2021
e467ec6
Update PSBT::UpdatePSBTOutput to use GetUnsignedTx
achow101 Jan 18, 2021
2c1fe58
Allow and create PSBTv2 in RPCs
achow101 Jan 18, 2021
ebc49e3
Allow createpsbt and walletcreatefundedpsbt to take psbt version
achow101 Jan 25, 2021
f4bca18
Restrict joinpsbts to PSBTv0 only
achow101 Jan 25, 2021
0ca0b7e
Update rpc_psbt.py to test PSBTv0 explicitly in some places
achow101 Jan 25, 2021
e860cd0
Add a PSBT constructor for providing the version
achow101 Apr 5, 2021
ecaf5ea
Use GetUnsignedTx when serializing in PSBTv0
achow101 Apr 5, 2021
b372430
Implement PSET fields and their de/ser
achow101 Mar 6, 2021
e374397
Implement and enable decodepsbt for PSET
achow101 Mar 16, 2021
f84a927
Add DecomposePeginWitness
achow101 May 4, 2021
ee28be3
Extract elements fields for tx into psbt
achow101 Mar 18, 2021
33c694f
Helper functions to determine whether a PSBTOutput is blinded
achow101 Mar 18, 2021
2220d84
Return peg-in UTXO with GetUTXO
achow101 Mar 18, 2021
6890461
Implement blinded combiner stuff
achow101 Mar 19, 2021
79c4a99
pset: add issuance things
achow101 Mar 23, 2021
bdfcb43
Add calculateasset RPC
achow101 Jul 15, 2020
1dbc3b2
Implement updatepsbtpegin RPC
achow101 Jul 16, 2020
e7dd046
Implement BlindPSBT
achow101 Sep 17, 2020
3f6c8bf
Add walletblindpsbt rpc
achow101 Oct 8, 2020
9a450ec
Set blinder_index to self in walletcreatefundedpsbt
achow101 Nov 25, 2020
bad1876
Re-enable and fix PSBT signing
achow101 Mar 25, 2021
e6cc0fd
Have walletprocesspsbt blind before signing
achow101 Dec 2, 2020
ea2c3df
Remove output_assets and have asset field in outputs
achow101 Mar 25, 2021
5391095
Output PSBTOutputs with aux info from ConstructTransaction
achow101 Mar 26, 2021
f686e0f
Remove walletfillpsbtdata RPC
achow101 Mar 26, 2021
124efa2
Return better errors for BlindingStatus
achow101 Dec 9, 2020
a8a6f4c
Add IsBlinded and IsFullyBlinded helpers for PSBT
achow101 Dec 9, 2020
3db2622
Only sign blinded PSBTs in walletprocesspsbt
achow101 Dec 9, 2020
eeb6cf7
Mark PSET as being implemented
achow101 Dec 16, 2020
e9bfff2
Allow empty scriptPubKeys
achow101 Apr 16, 2021
25df8aa
Fixes to FillPSBT
achow101 Apr 16, 2021
2c0cee5
Update GetUnsignedTx for PSET
achow101 Apr 19, 2021
c0cb623
Allow value commitments instead of explicit value
achow101 Apr 19, 2021
bd97836
Update FinalizeAndExtract for PSEt
achow101 Apr 19, 2021
0e2f1ff
Make m_peg_in_witness during SignPSBTInput
achow101 Apr 20, 2021
d8fa5c1
Use createtx array outputs
achow101 Apr 21, 2021
b1ebc81
Remove walletsignpsbt, blindpsbt, walletblindpsbt, and
achow101 Apr 21, 2021
46ccf61
Only allow psbt_version 2
achow101 May 4, 2021
afd7950
Update rpc_psbt.py for PSET
achow101 May 5, 2021
1889554
Remove unnecessary psbt blinding test
achow101 May 7, 2021
80ff739
Default to adding bip32 derivs
achow101 May 11, 2021
b65a00f
Add PSBTOutput::GetTxOut()
achow101 May 3, 2021
64b30bf
Enable analyzepsbt
achow101 May 12, 2021
7533503
Initialize optionals with nullopt
achow101 Jun 9, 2021
9fe6401
Allow specifying SIGHASH_RANGEPROOF
achow101 Jun 9, 2021
4a44ff2
Check elements blinding field constraints during deser
achow101 Jun 9, 2021
4940cee
Use a constant for maximum surjection targets
achow101 Jun 17, 2021
5425da4
Enable converttopsbt for PSET
achow101 Jun 18, 2021
864f625
Fix display of outputs in PSBT ops dialog
achow101 Jun 18, 2021
f8553c5
Disable joinpsbts
achow101 Jun 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions doc/pset.mediawiki
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
Note that this format is not yet implemented by Elements.

<pre>
BIP: PSET
Layer: Applications
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ BITCOIN_CORE_H = \
bech32.h \
blech32.h \
blind.h \
blindpsbt.h \
blockencodings.h \
blockfilter.h \
block_proof.h \
Expand Down Expand Up @@ -523,6 +524,7 @@ libbitcoin_common_a_SOURCES = \
bech32.cpp \
blech32.cpp \
blind.cpp \
blindpsbt.cpp \
block_proof.cpp \
bloom.cpp \
chainparams.cpp \
Expand Down
4 changes: 2 additions & 2 deletions src/blind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include <random.h>
#include <util/system.h>

static secp256k1_context* secp256k1_blind_context = NULL;
secp256k1_context* secp256k1_blind_context = NULL;

class Blind_ECC_Init {
public:
Expand Down Expand Up @@ -192,7 +192,7 @@ bool SurjectOutput(CTxOutWitness& txoutwit, const std::vector<secp256k1_fixed_as
{
int ret;
// 1 to 3 targets
size_t nInputsToSelect = std::min((size_t)3, surjection_targets.size());
size_t nInputsToSelect = std::min(MAX_SURJECTION_TARGETS, surjection_targets.size());
unsigned char randseed[32];
GetStrongRandBytes(randseed, 32);
size_t input_index;
Expand Down
5 changes: 5 additions & 0 deletions src/blind.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ static const size_t MAX_RANGEPROOF_SIZE = 5126;
static const size_t DEFAULT_SURJECTIONPROOF_SIZE = 135;
// 32 bytes of asset type, 32 bytes of asset blinding factor in sidechannel
static const size_t SIDECHANNEL_MSG_SIZE = 64;
// Maximum number of inputs to select for surjection proof
static const size_t MAX_SURJECTION_TARGETS = 3;

// Blinding context
extern secp256k1_context* secp256k1_blind_context;

/*
* Verify a pair of confidential asset and value, given the blinding factors for both.
Expand Down
426 changes: 426 additions & 0 deletions src/blindpsbt.cpp

Large diffs are not rendered by default.

40 changes: 40 additions & 0 deletions src/blindpsbt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) 2020 The Elements Core developers
// // Distributed under the MIT software license, see the accompanying
// // file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_BLINDPSBT_H
#define BITCOIN_BLINDPSBT_H

#include <blind.h>
#include <key.h>
#include <pubkey.h>
#include <primitives/transaction.h>
#include <primitives/confidential.h>

#include <secp256k1.h>
#include <secp256k1_rangeproof.h>
#include <secp256k1_surjectionproof.h>

struct PartiallySignedTransaction;

enum class BlindingStatus
{
OK, //!< No error
NEEDS_UTXOS,
INVALID_ASSET,
INVALID_ASSET_COMMITMENT,
SCALAR_UNABLE,
INVALID_BLINDER,
ASP_UNABLE,
};

std::string GetBlindingStatusError(const BlindingStatus& status);

bool CreateAssetSurjectionProof(std::vector<unsigned char>& output_proof, const std::vector<secp256k1_fixed_asset_tag>& fixed_input_tags, const std::vector<secp256k1_generator>& ephemeral_input_tags, const std::vector<uint256>& input_asset_blinders, const uint256& output_asset_blinder, const secp256k1_generator& output_asset_tag, const CAsset& asset);
uint256 GenerateRangeproofECDHKey(CPubKey& ephemeral_pubkey, const CPubKey blinding_pubkey);
bool CreateValueRangeProof(std::vector<unsigned char>& rangeproof, const uint256& value_blinder, const uint256& nonce, const CAmount amount, const CScript& scriptPubKey, const secp256k1_pedersen_commitment& value_commit, const secp256k1_generator& gen, const CAsset& asset, const uint256& asset_blinder);
void CreateAssetCommitment(CConfidentialAsset& conf_asset, secp256k1_generator& asset_gen, const CAsset& asset, const uint256& asset_blinder);
void CreateValueCommitment(CConfidentialValue& conf_value, secp256k1_pedersen_commitment& value_commit, const uint256& value_blinder, const secp256k1_generator& asset_gen, const CAmount amount);
BlindingStatus BlindPSBT(PartiallySignedTransaction& psbt, std::map<uint32_t, std::tuple<CAmount, CAsset, uint256, uint256>> our_input_data, std::map<uint32_t, std::pair<CKey, CKey>> our_issuances_to_blind);

#endif //BITCOIN_BLINDPSBT_H
6 changes: 6 additions & 0 deletions src/core_read.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,16 @@ int ParseSighashString(const UniValue& sighash)
static std::map<std::string, int> map_sighash_values = {
{std::string("ALL"), int(SIGHASH_ALL)},
{std::string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)},
{std::string("ALL|RANGEPROOF"), int(SIGHASH_ALL|SIGHASH_RANGEPROOF)},
{std::string("ALL|ANYONECANPAY|RANGEPROOF"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY|SIGHASH_RANGEPROOF)},
{std::string("NONE"), int(SIGHASH_NONE)},
{std::string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY)},
{std::string("NONE|RANGEPROOF"), int(SIGHASH_NONE|SIGHASH_RANGEPROOF)},
{std::string("NONE|ANYONECANPAY|RANGEPROOF"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY|SIGHASH_RANGEPROOF)},
{std::string("SINGLE"), int(SIGHASH_SINGLE)},
{std::string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)},
{std::string("SINGLE|RANGEPROOF"), int(SIGHASH_SINGLE|SIGHASH_RANGEPROOF)},
{std::string("SINGLE|ANYONECANPAY|RANGEPROOF"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY|SIGHASH_RANGEPROOF)},
};
std::string strHashType = sighash.get_str();
const auto& it = map_sighash_values.find(strHashType);
Expand Down
136 changes: 72 additions & 64 deletions src/node/psbt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
// Go through each input and build status
PSBTAnalysis result;

bool calc_fee = true;
CAmountMap in_amts;
// Elements things
bool needs_blinded_outputs = false;
bool has_blinded_outputs = false;

result.inputs.resize(psbtx.tx->vin.size());
result.inputs.resize(psbtx.inputs.size());

for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
PSBTInput& input = psbtx.inputs[i];
PSBTInputAnalysis& input_analysis = result.inputs[i];

Expand All @@ -31,23 +32,24 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)

// Check for a UTXO
CTxOut utxo;
if (psbtx.GetInputUTXO(utxo, i)) {
//TODO(gwillen) do PSBT inputs always have explicit assets & amounts?
if (!MoneyRange(utxo.nValue.GetAmount()) || !MoneyRange(in_amts[utxo.nAsset.GetAsset()] + utxo.nValue.GetAmount())) {
result.SetInvalid(strprintf("PSBT is not valid. Input %u has invalid value", i));
return result;
if (input.GetUTXO(utxo)) {
if (utxo.nValue.IsExplicit()) {
if (!MoneyRange(utxo.nValue.GetAmount())) {
result.SetInvalid(strprintf("PSBT is not valid. Input %u has invalid value", i));
return result;
}
} else {
needs_blinded_outputs = true;
}
in_amts[utxo.nAsset.GetAsset()] += utxo.nValue.GetAmount();
input_analysis.has_utxo = true;
} else {
if (input.non_witness_utxo && psbtx.tx->vin[i].prevout.n >= input.non_witness_utxo->vout.size()) {
if (input.non_witness_utxo && *input.prev_out >= input.non_witness_utxo->vout.size()) {
result.SetInvalid(strprintf("PSBT is not valid. Input %u specifies invalid prevout", i));
return result;
}
input_analysis.has_utxo = false;
input_analysis.is_final = false;
input_analysis.next = PSBTRole::UPDATER;
calc_fee = false;
}

if (!utxo.IsNull() && utxo.scriptPubKey.IsUnspendable()) {
Expand Down Expand Up @@ -84,71 +86,77 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
}
}

// Calculate next role for PSBT by grabbing "minimum" PSBTInput next role
result.next = PSBTRole::EXTRACTOR;
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
PSBTInputAnalysis& input_analysis = result.inputs[i];
result.next = std::min(result.next, input_analysis.next);
}
assert(result.next > PSBTRole::CREATOR);

if (calc_fee) {
// Get the output amount
CAmountMap out_amts = std::accumulate(psbtx.tx->vout.begin(), psbtx.tx->vout.end(), CAmountMap(),
[](CAmountMap a, const CTxOut& b) {
CAmount acc = a[b.nAsset.GetAsset()];
CAmount add = b.nValue.GetAmount();

if (!MoneyRange(acc) || !MoneyRange(add) || !MoneyRange(acc + add)) {
CAmountMap invalid;
invalid[::policyAsset] = CAmount(-1);
return invalid;
for (const PSBTOutput& output : psbtx.outputs) {
CTxOut txout = output.GetTxOut();
if (output.IsBlinded()) {
has_blinded_outputs = true;
if (!output.IsFullyBlinded()) {
result.next = PSBTRole::BLINDER;
}
} else {
// Find the fee output
if (txout.IsFee()) {
if (result.fee != nullopt) {
result.SetInvalid("There is more than one fee output");
return result;
}
a[b.nAsset.GetAsset()] += add;
return a;
result.fee = output.amount;
}
);
if (!MoneyRange(out_amts)) {
result.SetInvalid(strprintf("PSBT is not valid. Output amount invalid"));
}
if (txout.nValue.IsExplicit() && !MoneyRange(txout.nValue.GetAmount())) {
result.SetInvalid("PSBT is not valid. Output amount invalid");
return result;
}
}

// Get the fee
CAmountMap fee = in_amts - out_amts;
result.fee = fee;
if (result.fee == nullopt) {
result.SetInvalid("PSBT missing required fee output");
return result;
}

// Estimate the size
CMutableTransaction mtx(*psbtx.tx);
CCoinsView view_dummy;
CCoinsViewCache view(&view_dummy);
bool success = true;
if (needs_blinded_outputs && !has_blinded_outputs) {
result.SetInvalid("PSBT has blinded inputs but no blinded outputs. Must have at least one blinded output to balance with the inputs");
return result;
}

for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
PSBTInput& input = psbtx.inputs[i];
Coin newcoin;
// Estimate the size
CMutableTransaction mtx(psbtx.GetUnsignedTx());
CCoinsView view_dummy;
CCoinsViewCache view(&view_dummy);
bool success = true;

if (!SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, 1, nullptr, true) || !psbtx.GetInputUTXO(newcoin.out, i)) {
success = false;
break;
} else {
mtx.vin[i].scriptSig = input.final_script_sig;
mtx.witness.vtxinwit[i].scriptWitness = input.final_script_witness;
newcoin.nHeight = 1;
view.AddCoin(psbtx.tx->vin[i].prevout, std::move(newcoin), true);
}
}
for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
PSBTInput& input = psbtx.inputs[i];
Coin newcoin;

if (success) {
CTransaction ctx = CTransaction(mtx);
size_t size = GetVirtualTransactionSize(ctx, GetTransactionSigOpCost(ctx, view, STANDARD_SCRIPT_VERIFY_FLAGS));
result.estimated_vsize = size;
// Estimate fee rate
CFeeRate feerate(fee[::policyAsset], size);
result.estimated_feerate = feerate;
if (!SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, 1, nullptr, true) || !input.GetUTXO(newcoin.out)) {
success = false;
break;
} else {
mtx.vin[i].scriptSig = input.final_script_sig;
mtx.witness.vtxinwit[i].scriptWitness = input.final_script_witness;
newcoin.nHeight = 1;
view.AddCoin(input.GetOutPoint(), std::move(newcoin), true);
}
}

if (success) {
CTransaction ctx = CTransaction(mtx);
size_t size = GetVirtualTransactionSize(ctx, GetTransactionSigOpCost(ctx, view, STANDARD_SCRIPT_VERIFY_FLAGS));
result.estimated_vsize = size;
// Estimate fee rate
CFeeRate feerate(*result.fee, size);
result.estimated_feerate = feerate;
}

// Calculate next role for PSBT by grabbing "minimum" PSBTInput next role
result.next = PSBTRole::EXTRACTOR;
for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
PSBTInputAnalysis& input_analysis = result.inputs[i];
result.next = std::min(result.next, input_analysis.next);
}
assert(result.next > PSBTRole::CREATOR);

return result;
}

2 changes: 1 addition & 1 deletion src/node/psbt.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ struct PSBTInputAnalysis {
struct PSBTAnalysis {
Optional<size_t> estimated_vsize; //!< Estimated weight of the transaction
Optional<CFeeRate> estimated_feerate; //!< Estimated feerate (fee / weight) of the transaction
Optional<CAmountMap> fee; //!< Amount of fee being paid by the transaction
Optional<CAmount> fee; //!< Amount of fee being paid by the transaction
std::vector<PSBTInputAnalysis> inputs; //!< More information about the individual inputs of the transaction
PSBTRole next; //!< Which of the BIP 174 roles needs to handle the transaction next
std::string error; //!< Error message
Expand Down
43 changes: 43 additions & 0 deletions src/pegins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,3 +533,46 @@ CScriptWitness CreatePeginWitness(const CAmount& value, const CAsset& asset, con
{
return CreatePeginWitnessInner(value, asset, genesis_hash, claim_script, tx_ref, merkle_block);
}

bool DecomposePeginWitness(const CScriptWitness& witness, CAmount& value, CAsset& asset, uint256& genesis_hash, CScript& claim_script, boost::variant<boost::blank, Sidechain::Bitcoin::CTransactionRef, CTransactionRef>& tx, boost::variant<boost::blank, Sidechain::Bitcoin::CMerkleBlock, CMerkleBlock>& merkle_block)
{
const auto& stack = witness.stack;

if (stack.size() < 5) return false;

CDataStream stream(stack[0], SER_NETWORK, PROTOCOL_VERSION);
stream >> value;

CAsset tmp_asset(stack[1]);
asset = tmp_asset;

uint256 gh(stack[2]);
genesis_hash = gh;

CScript s(stack[3].begin(), stack[3].end());
claim_script = s;

CDataStream ss_tx(stack[4], SER_NETWORK, PROTOCOL_VERSION);
if (Params().GetConsensus().ParentChainHasPow()) {
Sidechain::Bitcoin::CTransactionRef btc_tx;
ss_tx >> btc_tx;
tx = btc_tx;
} else {
CTransactionRef elem_tx;
ss_tx >> elem_tx;
tx = elem_tx;
}

CDataStream ss_proof(stack[5], SER_NETWORK, PROTOCOL_VERSION);
if (Params().GetConsensus().ParentChainHasPow()) {
Sidechain::Bitcoin::CMerkleBlock tx_proof;
ss_proof >> tx_proof;
merkle_block = tx_proof;
} else {
CMerkleBlock tx_proof;
ss_proof >> tx_proof;
merkle_block = tx_proof;
}

return true;
}
4 changes: 4 additions & 0 deletions src/pegins.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include <script/script.h>
#include <chain.h>

#include <boost/variant.hpp>

/** Calculates script necessary for p2ch peg-in transactions */
CScript calculate_contract(const CScript& federationRedeemScript, const CScript& witnessProgram);
bool GetAmountFromParentChainPegin(CAmount& amount, const Sidechain::Bitcoin::CTransaction& txBTC, unsigned int nOut);
Expand Down Expand Up @@ -42,5 +44,7 @@ std::vector<std::pair<CScript, CScript>> GetValidFedpegScripts(const CBlockIndex
CScriptWitness CreatePeginWitness(const CAmount& value, const CAsset& asset, const uint256& genesis_hash, const CScript& claim_script, const CTransactionRef& tx_ref, const CMerkleBlock& merkle_block);
CScriptWitness CreatePeginWitness(const CAmount& value, const CAsset& asset, const uint256& genesis_hash, const CScript& claim_script, const Sidechain::Bitcoin::CTransactionRef& tx_ref, const Sidechain::Bitcoin::CMerkleBlock& merkle_block);

/** Break out the individual parts of the peg-in witness stack */
bool DecomposePeginWitness(const CScriptWitness& witness, CAmount& value, CAsset& asset, uint256& genesis_hash, CScript& claim_script, boost::variant<boost::blank, Sidechain::Bitcoin::CTransactionRef, CTransactionRef>& tx, boost::variant<boost::blank, Sidechain::Bitcoin::CMerkleBlock, CMerkleBlock>& merkle_block);
achow101 marked this conversation as resolved.
Show resolved Hide resolved

#endif // BITCOIN_PEGINS_H
2 changes: 2 additions & 0 deletions src/primitives/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

bool g_con_elementsmode = false;

const int32_t CTransaction::CURRENT_VERSION = 2;

std::string COutPoint::ToString() const
{
return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10), n);
Expand Down
7 changes: 6 additions & 1 deletion src/primitives/transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,11 @@ class CTxOut
}

std::string ToString() const;

friend bool operator<(const CTxOut& a, const CTxOut& b)
{
return a.scriptPubKey < b.scriptPubKey;
}
};

struct CMutableTransaction;
Expand Down Expand Up @@ -477,7 +482,7 @@ class CTransaction
{
public:
// Default transaction version.
static const int32_t CURRENT_VERSION=2;
static const int32_t CURRENT_VERSION;

// Changing the default transaction version requires a two step process: first
// adapting relay policy by bumping MAX_STANDARD_VERSION, and then later date
Expand Down
Loading