mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-14 12:43:40 +02:00
Merge #730: Change Proprietary types to use the method specified in BIP 174
34e135011Use Elements PSBT magic when in Elements mode (Andrew Chow)3fa355c76Change Proprietary types to use the method specified in BIP 174 (Andrew Chow) Pull request description: https://github.com/bitcoin/bips/pull/849 (not yet merged) adds to BIP 174 proprietary types. This PR changes the PSBT types used in Elements to be in line with the proposed changes to the BIP/ Tree-SHA512: 73085a16005448d9f6ad1b74da4a40043ec29738256a439f35106793d11d0e95cb8d728db5cfefe1ddd49cd80367f7f5790d09efaa95bc443e1d6ba295240c4d
This commit is contained in:
commit
4b2fac45b9
1 changed files with 191 additions and 139 deletions
330
src/psbt.h
330
src/psbt.h
|
|
@ -13,9 +13,11 @@
|
|||
|
||||
// Magic bytes
|
||||
static constexpr uint8_t PSBT_MAGIC_BYTES[5] = {'p', 's', 'b', 't', 0xff};
|
||||
static constexpr uint8_t PSBT_ELEMENTS_MAGIC_BYTES[5] = {'p', 's', 'e', 't', 0xff};
|
||||
|
||||
// Global types
|
||||
static constexpr uint8_t PSBT_GLOBAL_UNSIGNED_TX = 0x00;
|
||||
static constexpr uint8_t PSBT_GLOBAL_PROPRIETARY = 0xFC;
|
||||
|
||||
// Input types
|
||||
static constexpr uint8_t PSBT_IN_NON_WITNESS_UTXO = 0x00;
|
||||
|
|
@ -27,26 +29,30 @@ static constexpr uint8_t PSBT_IN_WITNESSSCRIPT = 0x05;
|
|||
static constexpr uint8_t PSBT_IN_BIP32_DERIVATION = 0x06;
|
||||
static constexpr uint8_t PSBT_IN_SCRIPTSIG = 0x07;
|
||||
static constexpr uint8_t PSBT_IN_SCRIPTWITNESS = 0x08;
|
||||
static constexpr uint8_t PSBT_IN_PROPRIETARY = 0xFC;
|
||||
// Confidential Assets stuff (private use area)
|
||||
static constexpr uint8_t PSBT_IN_VALUE = 0xf0;
|
||||
static constexpr uint8_t PSBT_IN_VALUE_BLINDER = 0xf1;
|
||||
static constexpr uint8_t PSBT_IN_ASSET = 0xf2;
|
||||
static constexpr uint8_t PSBT_IN_ASSET_BLINDER = 0xf3;
|
||||
static constexpr uint8_t PSBT_IN_VALUE = 0x00;
|
||||
static constexpr uint8_t PSBT_IN_VALUE_BLINDER = 0x01;
|
||||
static constexpr uint8_t PSBT_IN_ASSET = 0x02;
|
||||
static constexpr uint8_t PSBT_IN_ASSET_BLINDER = 0x03;
|
||||
|
||||
// Output types
|
||||
static constexpr uint8_t PSBT_OUT_REDEEMSCRIPT = 0x00;
|
||||
static constexpr uint8_t PSBT_OUT_WITNESSSCRIPT = 0x01;
|
||||
static constexpr uint8_t PSBT_OUT_BIP32_DERIVATION = 0x02;
|
||||
static constexpr uint8_t PSBT_OUT_PROPRIETARY = 0xFC;
|
||||
// Confidential Assets stuff (private use area)
|
||||
static constexpr uint8_t PSBT_OUT_VALUE_COMMITMENT = 0xf0;
|
||||
static constexpr uint8_t PSBT_OUT_VALUE_BLINDER = 0xf1;
|
||||
static constexpr uint8_t PSBT_OUT_ASSET_COMMITMENT = 0xf2;
|
||||
static constexpr uint8_t PSBT_OUT_ASSET_BLINDER = 0xf3;
|
||||
static constexpr uint8_t PSBT_OUT_RANGE_PROOF = 0xf4;
|
||||
static constexpr uint8_t PSBT_OUT_SURJECTION_PROOF = 0xf5;
|
||||
static constexpr uint8_t PSBT_OUT_BLINDING_PUBKEY = 0xf6;
|
||||
static constexpr uint8_t PSBT_OUT_NONCE_COMMITMENT = 0xf7;
|
||||
static constexpr uint8_t PSBT_OUT_VALUE_COMMITMENT = 0x00;
|
||||
static constexpr uint8_t PSBT_OUT_VALUE_BLINDER = 0x01;
|
||||
static constexpr uint8_t PSBT_OUT_ASSET_COMMITMENT = 0x02;
|
||||
static constexpr uint8_t PSBT_OUT_ASSET_BLINDER = 0x03;
|
||||
static constexpr uint8_t PSBT_OUT_RANGE_PROOF = 0x04;
|
||||
static constexpr uint8_t PSBT_OUT_SURJECTION_PROOF = 0x05;
|
||||
static constexpr uint8_t PSBT_OUT_BLINDING_PUBKEY = 0x06;
|
||||
static constexpr uint8_t PSBT_OUT_NONCE_COMMITMENT = 0x07;
|
||||
|
||||
// Proprietary type identifer string
|
||||
static const std::string PSBT_ELEMENTS_ID("elements");
|
||||
|
||||
// The separator is 0x00. Reading this in means that the unserializer can interpret it
|
||||
// as a 0 length key which indicates that this is the separator. The separator has no value.
|
||||
|
|
@ -122,22 +128,22 @@ struct PSBTInput
|
|||
|
||||
// Write the Confidential Assets blinding data
|
||||
if (value) {
|
||||
SerializeToVector(s, PSBT_IN_VALUE);
|
||||
SerializeToVector(s, PSBT_IN_PROPRIETARY, PSBT_ELEMENTS_ID, PSBT_IN_VALUE);
|
||||
SerializeToVector(s, *value);
|
||||
}
|
||||
|
||||
if (!value_blinding_factor.IsNull()) {
|
||||
SerializeToVector(s, PSBT_IN_VALUE_BLINDER);
|
||||
SerializeToVector(s, PSBT_IN_PROPRIETARY, PSBT_ELEMENTS_ID, PSBT_IN_VALUE_BLINDER);
|
||||
SerializeToVector(s, value_blinding_factor);
|
||||
}
|
||||
|
||||
if (!asset.IsNull()) {
|
||||
SerializeToVector(s, PSBT_IN_ASSET);
|
||||
SerializeToVector(s, PSBT_IN_PROPRIETARY, PSBT_ELEMENTS_ID, PSBT_IN_ASSET);
|
||||
SerializeToVector(s, asset);
|
||||
}
|
||||
|
||||
if (!asset_blinding_factor.IsNull()) {
|
||||
SerializeToVector(s, PSBT_IN_ASSET_BLINDER);
|
||||
SerializeToVector(s, PSBT_IN_PROPRIETARY, PSBT_ELEMENTS_ID, PSBT_IN_ASSET_BLINDER);
|
||||
SerializeToVector(s, asset_blinding_factor);
|
||||
}
|
||||
|
||||
|
|
@ -279,46 +285,64 @@ struct PSBTInput
|
|||
UnserializeFromVector(s, final_script_witness.stack);
|
||||
break;
|
||||
}
|
||||
case PSBT_IN_VALUE:
|
||||
case PSBT_IN_PROPRIETARY:
|
||||
{
|
||||
if (value != boost::none) {
|
||||
throw std::ios_base::failure("Duplicate Key, input value already provided");
|
||||
} else if (key.size() != 1) {
|
||||
throw std::ios_base::failure("Final value key is more than one byte type");
|
||||
VectorReader skey(s.GetType(), s.GetVersion(), key, 1);
|
||||
std::string identifier;
|
||||
skey >> identifier;
|
||||
|
||||
if (identifier != PSBT_ELEMENTS_ID) {
|
||||
// This is not our proprietary type, skip it
|
||||
continue;
|
||||
}
|
||||
CAmount amt;
|
||||
UnserializeFromVector(s, amt);
|
||||
value = amt;
|
||||
break;
|
||||
}
|
||||
case PSBT_IN_VALUE_BLINDER:
|
||||
{
|
||||
if (!value_blinding_factor.IsNull()) {
|
||||
throw std::ios_base::failure("Duplicate Key, input value_blinding_factor already provided");
|
||||
} else if (key.size() != 1) {
|
||||
throw std::ios_base::failure("Final value_blinding_factor key is more than one byte type");
|
||||
|
||||
size_t subkey_len = skey.size();
|
||||
uint64_t subtype = ReadCompactSize(skey);
|
||||
|
||||
switch(subtype) {
|
||||
case PSBT_IN_VALUE:
|
||||
{
|
||||
if (value != boost::none) {
|
||||
throw std::ios_base::failure("Duplicate Key, input value already provided");
|
||||
} else if (subkey_len != 1) {
|
||||
throw std::ios_base::failure("Final value key is more than one byte type");
|
||||
}
|
||||
CAmount amt;
|
||||
UnserializeFromVector(s, amt);
|
||||
value = amt;
|
||||
break;
|
||||
}
|
||||
case PSBT_IN_VALUE_BLINDER:
|
||||
{
|
||||
if (!value_blinding_factor.IsNull()) {
|
||||
throw std::ios_base::failure("Duplicate Key, input value_blinding_factor already provided");
|
||||
} else if (subkey_len != 1) {
|
||||
throw std::ios_base::failure("Final value_blinding_factor key is more than one byte type");
|
||||
}
|
||||
UnserializeFromVector(s, value_blinding_factor);
|
||||
break;
|
||||
}
|
||||
case PSBT_IN_ASSET:
|
||||
{
|
||||
if (!asset.IsNull()) {
|
||||
throw std::ios_base::failure("Duplicate Key, input asset already provided");
|
||||
} else if (subkey_len != 1) {
|
||||
throw std::ios_base::failure("Final asset key is more than one byte type");
|
||||
}
|
||||
UnserializeFromVector(s, asset);
|
||||
break;
|
||||
}
|
||||
case PSBT_IN_ASSET_BLINDER:
|
||||
{
|
||||
if (!asset_blinding_factor.IsNull()) {
|
||||
throw std::ios_base::failure("Duplicate Key, input asset_blinding_factor already provided");
|
||||
} else if (subkey_len != 1) {
|
||||
throw std::ios_base::failure("Final asset_blinding_factor key is more than one byte type");
|
||||
}
|
||||
UnserializeFromVector(s, asset_blinding_factor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
UnserializeFromVector(s, value_blinding_factor);
|
||||
break;
|
||||
}
|
||||
case PSBT_IN_ASSET:
|
||||
{
|
||||
if (!asset.IsNull()) {
|
||||
throw std::ios_base::failure("Duplicate Key, input asset already provided");
|
||||
} else if (key.size() != 1) {
|
||||
throw std::ios_base::failure("Final asset key is more than one byte type");
|
||||
}
|
||||
UnserializeFromVector(s, asset);
|
||||
break;
|
||||
}
|
||||
case PSBT_IN_ASSET_BLINDER:
|
||||
{
|
||||
if (!asset_blinding_factor.IsNull()) {
|
||||
throw std::ios_base::failure("Duplicate Key, input asset_blinding_factor already provided");
|
||||
} else if (key.size() != 1) {
|
||||
throw std::ios_base::failure("Final asset_blinding_factor key is more than one byte type");
|
||||
}
|
||||
UnserializeFromVector(s, asset_blinding_factor);
|
||||
break;
|
||||
}
|
||||
// Unknown stuff
|
||||
|
|
@ -390,42 +414,42 @@ struct PSBTOutput
|
|||
if (g_con_elementsmode) {
|
||||
// Write the Confidential Assets blinding data
|
||||
if (!value_commitment.IsNull()) {
|
||||
SerializeToVector(s, PSBT_OUT_VALUE_COMMITMENT);
|
||||
SerializeToVector(s, PSBT_OUT_PROPRIETARY, PSBT_ELEMENTS_ID, PSBT_OUT_VALUE_COMMITMENT);
|
||||
SerializeToVector(s, value_commitment);
|
||||
}
|
||||
|
||||
if (!value_blinding_factor.IsNull()) {
|
||||
SerializeToVector(s, PSBT_OUT_VALUE_BLINDER);
|
||||
SerializeToVector(s, PSBT_OUT_PROPRIETARY, PSBT_ELEMENTS_ID, PSBT_OUT_VALUE_BLINDER);
|
||||
SerializeToVector(s, value_blinding_factor);
|
||||
}
|
||||
|
||||
if (!asset_commitment.IsNull()) {
|
||||
SerializeToVector(s, PSBT_OUT_ASSET_COMMITMENT);
|
||||
SerializeToVector(s, PSBT_OUT_PROPRIETARY, PSBT_ELEMENTS_ID, PSBT_OUT_ASSET_COMMITMENT);
|
||||
SerializeToVector(s, asset_commitment);
|
||||
}
|
||||
|
||||
if (!asset_blinding_factor.IsNull()) {
|
||||
SerializeToVector(s, PSBT_OUT_ASSET_BLINDER);
|
||||
SerializeToVector(s, PSBT_OUT_PROPRIETARY, PSBT_ELEMENTS_ID, PSBT_OUT_ASSET_BLINDER);
|
||||
SerializeToVector(s, asset_blinding_factor);
|
||||
}
|
||||
|
||||
if (!nonce_commitment.IsNull()) {
|
||||
SerializeToVector(s, PSBT_OUT_NONCE_COMMITMENT);
|
||||
SerializeToVector(s, PSBT_OUT_PROPRIETARY, PSBT_ELEMENTS_ID, PSBT_OUT_NONCE_COMMITMENT);
|
||||
SerializeToVector(s, nonce_commitment);
|
||||
}
|
||||
|
||||
if (!range_proof.empty()) {
|
||||
SerializeToVector(s, PSBT_OUT_RANGE_PROOF);
|
||||
SerializeToVector(s, PSBT_OUT_PROPRIETARY, PSBT_ELEMENTS_ID, PSBT_OUT_RANGE_PROOF);
|
||||
s << range_proof;
|
||||
}
|
||||
|
||||
if (!surjection_proof.empty()) {
|
||||
SerializeToVector(s, PSBT_OUT_SURJECTION_PROOF);
|
||||
SerializeToVector(s, PSBT_OUT_PROPRIETARY, PSBT_ELEMENTS_ID, PSBT_OUT_SURJECTION_PROOF);
|
||||
s << surjection_proof;
|
||||
}
|
||||
|
||||
if (blinding_pubkey.IsValid()) {
|
||||
SerializeToVector(s, PSBT_OUT_BLINDING_PUBKEY);
|
||||
SerializeToVector(s, PSBT_OUT_PROPRIETARY, PSBT_ELEMENTS_ID, PSBT_OUT_BLINDING_PUBKEY);
|
||||
s << blinding_pubkey;
|
||||
}
|
||||
}
|
||||
|
|
@ -486,84 +510,102 @@ struct PSBTOutput
|
|||
DeserializeHDKeypaths(s, key, hd_keypaths);
|
||||
break;
|
||||
}
|
||||
case PSBT_OUT_VALUE_COMMITMENT:
|
||||
case PSBT_OUT_PROPRIETARY:
|
||||
{
|
||||
if (!value_commitment.IsNull()) {
|
||||
throw std::ios_base::failure("Duplicate Key, output value_commitment already provided");
|
||||
} else if (key.size() != 1) {
|
||||
throw std::ios_base::failure("Output value_commitment key is more than one byte type");
|
||||
VectorReader skey(s.GetType(), s.GetVersion(), key, 1);
|
||||
std::string identifier;
|
||||
skey >> identifier;
|
||||
|
||||
if (identifier != PSBT_ELEMENTS_ID) {
|
||||
// This is not our proprietary type, skip it
|
||||
continue;
|
||||
}
|
||||
UnserializeFromVector(s, value_commitment);
|
||||
break;
|
||||
}
|
||||
case PSBT_OUT_VALUE_BLINDER:
|
||||
{
|
||||
if (!value_blinding_factor.IsNull()) {
|
||||
throw std::ios_base::failure("Duplicate Key, output value_blinding_factor already provided");
|
||||
} else if (key.size() != 1) {
|
||||
throw std::ios_base::failure("Output value_blinding_factor key is more than one byte type");
|
||||
|
||||
size_t subkey_len = skey.size();
|
||||
uint64_t subtype = ReadCompactSize(skey);
|
||||
|
||||
switch(subtype) {
|
||||
case PSBT_OUT_VALUE_COMMITMENT:
|
||||
{
|
||||
if (!value_commitment.IsNull()) {
|
||||
throw std::ios_base::failure("Duplicate Key, output value_commitment already provided");
|
||||
} else if (subkey_len != 1) {
|
||||
throw std::ios_base::failure("Output value_commitment key is more than one byte type");
|
||||
}
|
||||
UnserializeFromVector(s, value_commitment);
|
||||
break;
|
||||
}
|
||||
case PSBT_OUT_VALUE_BLINDER:
|
||||
{
|
||||
if (!value_blinding_factor.IsNull()) {
|
||||
throw std::ios_base::failure("Duplicate Key, output value_blinding_factor already provided");
|
||||
} else if (subkey_len != 1) {
|
||||
throw std::ios_base::failure("Output value_blinding_factor key is more than one byte type");
|
||||
}
|
||||
UnserializeFromVector(s, value_blinding_factor);
|
||||
break;
|
||||
}
|
||||
case PSBT_OUT_ASSET_COMMITMENT:
|
||||
{
|
||||
if (!asset_commitment.IsNull()) {
|
||||
throw std::ios_base::failure("Duplicate Key, output asset_commitment already provided");
|
||||
} else if (subkey_len != 1) {
|
||||
throw std::ios_base::failure("Output asset_commitment key is more than one byte type");
|
||||
}
|
||||
UnserializeFromVector(s, asset_commitment);
|
||||
break;
|
||||
}
|
||||
case PSBT_OUT_ASSET_BLINDER:
|
||||
{
|
||||
if (!asset_blinding_factor.IsNull()) {
|
||||
throw std::ios_base::failure("Duplicate Key, output asset_blinding_factor already provided");
|
||||
} else if (subkey_len != 1) {
|
||||
throw std::ios_base::failure("Output asset_blinding_factor key is more than one byte type");
|
||||
}
|
||||
UnserializeFromVector(s, asset_blinding_factor);
|
||||
break;
|
||||
}
|
||||
case PSBT_OUT_NONCE_COMMITMENT:
|
||||
{
|
||||
if (!nonce_commitment.IsNull()) {
|
||||
throw std::ios_base::failure("Duplicate Key, output nonce_commitment already provided");
|
||||
} else if (subkey_len != 1) {
|
||||
throw std::ios_base::failure("Output nonce_commitment key is more than one byte type");
|
||||
}
|
||||
UnserializeFromVector(s, nonce_commitment);
|
||||
break;
|
||||
}
|
||||
case PSBT_OUT_RANGE_PROOF:
|
||||
{
|
||||
if (!range_proof.empty()) {
|
||||
throw std::ios_base::failure("Duplicate Key, output range_proof already provided");
|
||||
} else if (subkey_len != 1) {
|
||||
throw std::ios_base::failure("Output range_proof key is more than one byte type");
|
||||
}
|
||||
s >> range_proof;
|
||||
break;
|
||||
}
|
||||
case PSBT_OUT_SURJECTION_PROOF:
|
||||
{
|
||||
if (!surjection_proof.empty()) {
|
||||
throw std::ios_base::failure("Duplicate Key, output surjection_proof already provided");
|
||||
} else if (subkey_len != 1) {
|
||||
throw std::ios_base::failure("Output surjection_proof key is more than one byte type");
|
||||
}
|
||||
s >> surjection_proof;
|
||||
break;
|
||||
}
|
||||
case PSBT_OUT_BLINDING_PUBKEY:
|
||||
{
|
||||
if (blinding_pubkey.IsValid()) {
|
||||
throw std::ios_base::failure("Duplicate Key, output blinding_pubkey already provided");
|
||||
} else if (subkey_len != 1) {
|
||||
throw std::ios_base::failure("Output blinding_pubkey key is more than one byte type");
|
||||
}
|
||||
s >> blinding_pubkey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
UnserializeFromVector(s, value_blinding_factor);
|
||||
break;
|
||||
}
|
||||
case PSBT_OUT_ASSET_COMMITMENT:
|
||||
{
|
||||
if (!asset_commitment.IsNull()) {
|
||||
throw std::ios_base::failure("Duplicate Key, output asset_commitment already provided");
|
||||
} else if (key.size() != 1) {
|
||||
throw std::ios_base::failure("Output asset_commitment key is more than one byte type");
|
||||
}
|
||||
UnserializeFromVector(s, asset_commitment);
|
||||
break;
|
||||
}
|
||||
case PSBT_OUT_ASSET_BLINDER:
|
||||
{
|
||||
if (!asset_blinding_factor.IsNull()) {
|
||||
throw std::ios_base::failure("Duplicate Key, output asset_blinding_factor already provided");
|
||||
} else if (key.size() != 1) {
|
||||
throw std::ios_base::failure("Output asset_blinding_factor key is more than one byte type");
|
||||
}
|
||||
UnserializeFromVector(s, asset_blinding_factor);
|
||||
break;
|
||||
}
|
||||
case PSBT_OUT_NONCE_COMMITMENT:
|
||||
{
|
||||
if (!nonce_commitment.IsNull()) {
|
||||
throw std::ios_base::failure("Duplicate Key, output nonce_commitment already provided");
|
||||
} else if (key.size() != 1) {
|
||||
throw std::ios_base::failure("Output nonce_commitment key is more than one byte type");
|
||||
}
|
||||
UnserializeFromVector(s, nonce_commitment);
|
||||
break;
|
||||
}
|
||||
case PSBT_OUT_RANGE_PROOF:
|
||||
{
|
||||
if (!range_proof.empty()) {
|
||||
throw std::ios_base::failure("Duplicate Key, output range_proof already provided");
|
||||
} else if (key.size() != 1) {
|
||||
throw std::ios_base::failure("Output range_proof key is more than one byte type");
|
||||
}
|
||||
s >> range_proof;
|
||||
break;
|
||||
}
|
||||
case PSBT_OUT_SURJECTION_PROOF:
|
||||
{
|
||||
if (!surjection_proof.empty()) {
|
||||
throw std::ios_base::failure("Duplicate Key, output surjection_proof already provided");
|
||||
} else if (key.size() != 1) {
|
||||
throw std::ios_base::failure("Output surjection_proof key is more than one byte type");
|
||||
}
|
||||
s >> surjection_proof;
|
||||
break;
|
||||
}
|
||||
case PSBT_OUT_BLINDING_PUBKEY:
|
||||
{
|
||||
if (blinding_pubkey.IsValid()) {
|
||||
throw std::ios_base::failure("Duplicate Key, output blinding_pubkey already provided");
|
||||
} else if (key.size() != 1) {
|
||||
throw std::ios_base::failure("Output blinding_pubkey key is more than one byte type");
|
||||
}
|
||||
s >> blinding_pubkey;
|
||||
break;
|
||||
}
|
||||
// Unknown stuff
|
||||
|
|
@ -623,7 +665,11 @@ struct PartiallySignedTransaction
|
|||
inline void Serialize(Stream& s) const {
|
||||
|
||||
// magic bytes
|
||||
s << PSBT_MAGIC_BYTES;
|
||||
if (g_con_elementsmode) {
|
||||
s << PSBT_ELEMENTS_MAGIC_BYTES;
|
||||
} else {
|
||||
s << PSBT_MAGIC_BYTES;
|
||||
}
|
||||
|
||||
// unsigned tx flag
|
||||
SerializeToVector(s, PSBT_GLOBAL_UNSIGNED_TX);
|
||||
|
|
@ -657,8 +703,14 @@ struct PartiallySignedTransaction
|
|||
// Read the magic bytes
|
||||
uint8_t magic[5];
|
||||
s >> magic;
|
||||
if (!std::equal(magic, magic + 5, PSBT_MAGIC_BYTES)) {
|
||||
throw std::ios_base::failure("Invalid PSBT magic bytes");
|
||||
if (g_con_elementsmode) {
|
||||
if (!std::equal(magic, magic + 5, PSBT_ELEMENTS_MAGIC_BYTES)) {
|
||||
throw std::ios_base::failure("Invalid PSBT magic bytes");
|
||||
}
|
||||
} else {
|
||||
if (!std::equal(magic, magic + 5, PSBT_MAGIC_BYTES)) {
|
||||
throw std::ios_base::failure("Invalid PSBT magic bytes");
|
||||
}
|
||||
}
|
||||
|
||||
// Read global data
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue