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
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