Change Proprietary types to use the method specified in BIP 174

This commit is contained in:
Andrew Chow 2019-10-02 17:36:53 -04:00
parent ed03bfc899
commit 3fa355c767

View file

@ -13,9 +13,11 @@
// Magic bytes // Magic bytes
static constexpr uint8_t PSBT_MAGIC_BYTES[5] = {'p', 's', 'b', 't', 0xff}; 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 // Global types
static constexpr uint8_t PSBT_GLOBAL_UNSIGNED_TX = 0x00; static constexpr uint8_t PSBT_GLOBAL_UNSIGNED_TX = 0x00;
static constexpr uint8_t PSBT_GLOBAL_PROPRIETARY = 0xFC;
// Input types // Input types
static constexpr uint8_t PSBT_IN_NON_WITNESS_UTXO = 0x00; 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_BIP32_DERIVATION = 0x06;
static constexpr uint8_t PSBT_IN_SCRIPTSIG = 0x07; static constexpr uint8_t PSBT_IN_SCRIPTSIG = 0x07;
static constexpr uint8_t PSBT_IN_SCRIPTWITNESS = 0x08; static constexpr uint8_t PSBT_IN_SCRIPTWITNESS = 0x08;
static constexpr uint8_t PSBT_IN_PROPRIETARY = 0xFC;
// Confidential Assets stuff (private use area) // Confidential Assets stuff (private use area)
static constexpr uint8_t PSBT_IN_VALUE = 0xf0; static constexpr uint8_t PSBT_IN_VALUE = 0x00;
static constexpr uint8_t PSBT_IN_VALUE_BLINDER = 0xf1; static constexpr uint8_t PSBT_IN_VALUE_BLINDER = 0x01;
static constexpr uint8_t PSBT_IN_ASSET = 0xf2; static constexpr uint8_t PSBT_IN_ASSET = 0x02;
static constexpr uint8_t PSBT_IN_ASSET_BLINDER = 0xf3; static constexpr uint8_t PSBT_IN_ASSET_BLINDER = 0x03;
// Output types // Output types
static constexpr uint8_t PSBT_OUT_REDEEMSCRIPT = 0x00; static constexpr uint8_t PSBT_OUT_REDEEMSCRIPT = 0x00;
static constexpr uint8_t PSBT_OUT_WITNESSSCRIPT = 0x01; static constexpr uint8_t PSBT_OUT_WITNESSSCRIPT = 0x01;
static constexpr uint8_t PSBT_OUT_BIP32_DERIVATION = 0x02; static constexpr uint8_t PSBT_OUT_BIP32_DERIVATION = 0x02;
static constexpr uint8_t PSBT_OUT_PROPRIETARY = 0xFC;
// Confidential Assets stuff (private use area) // Confidential Assets stuff (private use area)
static constexpr uint8_t PSBT_OUT_VALUE_COMMITMENT = 0xf0; static constexpr uint8_t PSBT_OUT_VALUE_COMMITMENT = 0x00;
static constexpr uint8_t PSBT_OUT_VALUE_BLINDER = 0xf1; static constexpr uint8_t PSBT_OUT_VALUE_BLINDER = 0x01;
static constexpr uint8_t PSBT_OUT_ASSET_COMMITMENT = 0xf2; static constexpr uint8_t PSBT_OUT_ASSET_COMMITMENT = 0x02;
static constexpr uint8_t PSBT_OUT_ASSET_BLINDER = 0xf3; static constexpr uint8_t PSBT_OUT_ASSET_BLINDER = 0x03;
static constexpr uint8_t PSBT_OUT_RANGE_PROOF = 0xf4; static constexpr uint8_t PSBT_OUT_RANGE_PROOF = 0x04;
static constexpr uint8_t PSBT_OUT_SURJECTION_PROOF = 0xf5; static constexpr uint8_t PSBT_OUT_SURJECTION_PROOF = 0x05;
static constexpr uint8_t PSBT_OUT_BLINDING_PUBKEY = 0xf6; static constexpr uint8_t PSBT_OUT_BLINDING_PUBKEY = 0x06;
static constexpr uint8_t PSBT_OUT_NONCE_COMMITMENT = 0xf7; 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 // 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. // 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 // Write the Confidential Assets blinding data
if (value) { if (value) {
SerializeToVector(s, PSBT_IN_VALUE); SerializeToVector(s, PSBT_IN_PROPRIETARY, PSBT_ELEMENTS_ID, PSBT_IN_VALUE);
SerializeToVector(s, *value); SerializeToVector(s, *value);
} }
if (!value_blinding_factor.IsNull()) { 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); SerializeToVector(s, value_blinding_factor);
} }
if (!asset.IsNull()) { if (!asset.IsNull()) {
SerializeToVector(s, PSBT_IN_ASSET); SerializeToVector(s, PSBT_IN_PROPRIETARY, PSBT_ELEMENTS_ID, PSBT_IN_ASSET);
SerializeToVector(s, asset); SerializeToVector(s, asset);
} }
if (!asset_blinding_factor.IsNull()) { 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); SerializeToVector(s, asset_blinding_factor);
} }
@ -279,46 +285,64 @@ struct PSBTInput
UnserializeFromVector(s, final_script_witness.stack); UnserializeFromVector(s, final_script_witness.stack);
break; break;
} }
case PSBT_IN_VALUE: case PSBT_IN_PROPRIETARY:
{ {
if (value != boost::none) { VectorReader skey(s.GetType(), s.GetVersion(), key, 1);
throw std::ios_base::failure("Duplicate Key, input value already provided"); std::string identifier;
} else if (key.size() != 1) { skey >> identifier;
throw std::ios_base::failure("Final value key is more than one byte type");
if (identifier != PSBT_ELEMENTS_ID) {
// This is not our proprietary type, skip it
continue;
} }
CAmount amt;
UnserializeFromVector(s, amt); size_t subkey_len = skey.size();
value = amt; uint64_t subtype = ReadCompactSize(skey);
break;
} switch(subtype) {
case PSBT_IN_VALUE_BLINDER: case PSBT_IN_VALUE:
{ {
if (!value_blinding_factor.IsNull()) { if (value != boost::none) {
throw std::ios_base::failure("Duplicate Key, input value_blinding_factor already provided"); throw std::ios_base::failure("Duplicate Key, input value already provided");
} else if (key.size() != 1) { } else if (subkey_len != 1) {
throw std::ios_base::failure("Final value_blinding_factor key is more than one byte type"); 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; break;
} }
// Unknown stuff // Unknown stuff
@ -390,42 +414,42 @@ struct PSBTOutput
if (g_con_elementsmode) { if (g_con_elementsmode) {
// Write the Confidential Assets blinding data // Write the Confidential Assets blinding data
if (!value_commitment.IsNull()) { 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); SerializeToVector(s, value_commitment);
} }
if (!value_blinding_factor.IsNull()) { 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); SerializeToVector(s, value_blinding_factor);
} }
if (!asset_commitment.IsNull()) { 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); SerializeToVector(s, asset_commitment);
} }
if (!asset_blinding_factor.IsNull()) { 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); SerializeToVector(s, asset_blinding_factor);
} }
if (!nonce_commitment.IsNull()) { 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); SerializeToVector(s, nonce_commitment);
} }
if (!range_proof.empty()) { 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; s << range_proof;
} }
if (!surjection_proof.empty()) { 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; s << surjection_proof;
} }
if (blinding_pubkey.IsValid()) { 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; s << blinding_pubkey;
} }
} }
@ -486,84 +510,102 @@ struct PSBTOutput
DeserializeHDKeypaths(s, key, hd_keypaths); DeserializeHDKeypaths(s, key, hd_keypaths);
break; break;
} }
case PSBT_OUT_VALUE_COMMITMENT: case PSBT_OUT_PROPRIETARY:
{ {
if (!value_commitment.IsNull()) { VectorReader skey(s.GetType(), s.GetVersion(), key, 1);
throw std::ios_base::failure("Duplicate Key, output value_commitment already provided"); std::string identifier;
} else if (key.size() != 1) { skey >> identifier;
throw std::ios_base::failure("Output value_commitment key is more than one byte type");
if (identifier != PSBT_ELEMENTS_ID) {
// This is not our proprietary type, skip it
continue;
} }
UnserializeFromVector(s, value_commitment);
break; size_t subkey_len = skey.size();
} uint64_t subtype = ReadCompactSize(skey);
case PSBT_OUT_VALUE_BLINDER:
{ switch(subtype) {
if (!value_blinding_factor.IsNull()) { case PSBT_OUT_VALUE_COMMITMENT:
throw std::ios_base::failure("Duplicate Key, output value_blinding_factor already provided"); {
} else if (key.size() != 1) { if (!value_commitment.IsNull()) {
throw std::ios_base::failure("Output value_blinding_factor key is more than one byte type"); 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; break;
} }
// Unknown stuff // Unknown stuff