mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-15 12:51:00 +02:00
Add ConfidentialCommitment-based types
This commit is contained in:
parent
d0322f7f7d
commit
8b8256d9fa
3 changed files with 260 additions and 0 deletions
|
|
@ -373,6 +373,8 @@ libbitcoin_consensus_a_SOURCES = \
|
|||
prevector.h \
|
||||
primitives/block.cpp \
|
||||
primitives/block.h \
|
||||
primitives/confidential.cpp \
|
||||
primitives/confidential.h \
|
||||
primitives/txwitness.cpp \
|
||||
primitives/txwitness.h \
|
||||
primitives/transaction.cpp \
|
||||
|
|
|
|||
34
src/primitives/confidential.cpp
Normal file
34
src/primitives/confidential.cpp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
#include <primitives/confidential.h>
|
||||
|
||||
#include <tinyformat.h>
|
||||
|
||||
void CConfidentialAsset::SetToAsset(const CAsset& asset)
|
||||
{
|
||||
vchCommitment.clear();
|
||||
vchCommitment.reserve(nExplicitSize);
|
||||
vchCommitment.push_back(1);
|
||||
vchCommitment.insert(vchCommitment.end(), asset.begin(), asset.end());
|
||||
}
|
||||
|
||||
void CConfidentialValue::SetToAmount(const CAmount amount)
|
||||
{
|
||||
vchCommitment.resize(nExplicitSize);
|
||||
vchCommitment[0] = 1;
|
||||
WriteBE64(&vchCommitment[1], amount);
|
||||
}
|
||||
|
||||
std::string CAssetIssuance::ToString() const
|
||||
{
|
||||
std::string str;
|
||||
str += "CAssetIssuance(";
|
||||
str += assetBlindingNonce.ToString();
|
||||
str += ", ";
|
||||
str += assetEntropy.ToString();
|
||||
if (!nAmount.IsNull())
|
||||
str += strprintf(", amount=%s", (nAmount.IsExplicit() ? strprintf("%d.%08d", nAmount.GetAmount() / COIN, nAmount.GetAmount() % COIN) : std::string("CONFIDENTIAL")));
|
||||
if (!nInflationKeys.IsNull())
|
||||
str += strprintf(", inflationkeys=%s", (nInflationKeys.IsExplicit() ? strprintf("%d.%08d", nInflationKeys.GetAmount() / COIN, nInflationKeys.GetAmount() % COIN) : std::string("CONFIDENTIAL")));
|
||||
str += ")";
|
||||
return str;
|
||||
}
|
||||
224
src/primitives/confidential.h
Normal file
224
src/primitives/confidential.h
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
|
||||
#ifndef BITCOIN_PRIMITIVES_CONFIDENTIAL_H
|
||||
#define BITCOIN_PRIMITIVES_CONFIDENTIAL_H
|
||||
|
||||
#include <amount.h>
|
||||
#include <asset.h>
|
||||
#include <script/script.h>
|
||||
#include <serialize.h>
|
||||
#include <span.h>
|
||||
#include <uint256.h>
|
||||
#include <utilstrencodings.h>
|
||||
|
||||
extern bool g_con_elementswitness;
|
||||
|
||||
/**
|
||||
* Confidential assets, values, and nonces all share enough code in common
|
||||
* that it makes sense to define a common abstract base class. */
|
||||
template<size_t ExplicitSize, unsigned char PrefixA, unsigned char PrefixB>
|
||||
class CConfidentialCommitment
|
||||
{
|
||||
public:
|
||||
static const size_t nExplicitSize = ExplicitSize;
|
||||
static const size_t nCommittedSize = 33;
|
||||
|
||||
std::vector<unsigned char> vchCommitment;
|
||||
|
||||
CConfidentialCommitment() { SetNull(); }
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
unsigned char version = vchCommitment.empty()? 0: vchCommitment[0];
|
||||
READWRITE(version);
|
||||
if (ser_action.ForRead()) {
|
||||
switch (version) {
|
||||
/* Null */
|
||||
case 0:
|
||||
vchCommitment.clear();
|
||||
return;
|
||||
/* Explicit value */
|
||||
case 1:
|
||||
vchCommitment.resize(nExplicitSize);
|
||||
break;
|
||||
/* Confidential commitment */
|
||||
case PrefixA:
|
||||
case PrefixB:
|
||||
vchCommitment.resize(nCommittedSize);
|
||||
break;
|
||||
/* Invalid serialization! */
|
||||
default:
|
||||
throw std::ios_base::failure("Unrecognized serialization prefix");
|
||||
}
|
||||
vchCommitment[0] = version;
|
||||
}
|
||||
if (vchCommitment.size() > 1) {
|
||||
READWRITE(REF(Span<unsigned char>(vchCommitment.data() + 1, vchCommitment.size()-1)));
|
||||
}
|
||||
}
|
||||
|
||||
/* Null is the default state when no explicit asset or confidential
|
||||
* asset commitment has been set. */
|
||||
bool IsNull() const { return vchCommitment.empty(); }
|
||||
void SetNull() { vchCommitment.clear(); }
|
||||
|
||||
bool IsExplicit() const
|
||||
{
|
||||
return vchCommitment.size()==nExplicitSize && vchCommitment[0]==1;
|
||||
}
|
||||
|
||||
bool IsCommitment() const
|
||||
{
|
||||
return vchCommitment.size()==nCommittedSize && (vchCommitment[0]==PrefixA || vchCommitment[0]==PrefixB);
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return IsNull() || IsExplicit() || IsCommitment();
|
||||
}
|
||||
|
||||
std::string GetHex() const { return HexStr(vchCommitment); }
|
||||
|
||||
friend bool operator==(const CConfidentialCommitment& a, const CConfidentialCommitment& b)
|
||||
{
|
||||
return a.vchCommitment == b.vchCommitment;
|
||||
}
|
||||
|
||||
friend bool operator!=(const CConfidentialCommitment& a, const CConfidentialCommitment& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
};
|
||||
|
||||
/** A commitment to a blinded asset, or an explicit asset NUMS identifier */
|
||||
class CConfidentialAsset : public CConfidentialCommitment<33, 10, 11>
|
||||
{
|
||||
public:
|
||||
CConfidentialAsset() {
|
||||
SetNull();
|
||||
}
|
||||
CConfidentialAsset(CAsset asset) { SetToAsset(asset); }
|
||||
|
||||
void SetNull() {
|
||||
vchCommitment.clear();
|
||||
|
||||
// Set to dummy asset when not doing CA.
|
||||
if (!g_con_elementswitness) {
|
||||
SetToAsset(CAsset());
|
||||
}
|
||||
}
|
||||
|
||||
/* An explicit asset identifier is a 256-bit nothing-up-my-sleeve number
|
||||
* that used as auxiliary input to the Pedersen commitment setup to create
|
||||
* a generator which acts as the asset tag. */
|
||||
const CAsset& GetAsset() const
|
||||
{
|
||||
assert(IsExplicit());
|
||||
return *reinterpret_cast<const CAsset*>(&vchCommitment[1]);
|
||||
}
|
||||
void SetToAsset(const CAsset& asset);
|
||||
|
||||
};
|
||||
|
||||
/** A 33-byte commitment to a confidential value, or a 64-bit explicit value. */
|
||||
class CConfidentialValue : public CConfidentialCommitment<9, 8, 9>
|
||||
{
|
||||
public:
|
||||
CConfidentialValue() { SetNull(); }
|
||||
CConfidentialValue(CAmount nAmount) { SetToAmount(nAmount); }
|
||||
|
||||
/* An explicit value is called an amount. The first byte indicates it is
|
||||
* an explicit value, and the remaining 8 bytes is the value serialized as
|
||||
* a 64-bit big-endian integer. */
|
||||
CAmount GetAmount() const
|
||||
{
|
||||
if (!g_con_elementswitness && IsNull()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(IsExplicit());;
|
||||
return ReadBE64(&vchCommitment[1]);
|
||||
}
|
||||
void SetToAmount(CAmount nAmount);
|
||||
};
|
||||
|
||||
/**
|
||||
* A 33-byte data field that typically is used to convey to the
|
||||
* recipient the ECDH ephemeral key (an EC point) for deriving the
|
||||
* transaction output blinding factor. */
|
||||
class CConfidentialNonce : public CConfidentialCommitment<33, 2, 3>
|
||||
{
|
||||
public:
|
||||
CConfidentialNonce() { SetNull(); }
|
||||
};
|
||||
|
||||
/** A new asset issuance, or a reissuance (inflation) of an existing asset */
|
||||
class CAssetIssuance
|
||||
{
|
||||
public:
|
||||
// == 0
|
||||
// Indicates new asset issuance.
|
||||
// != 0
|
||||
// This is a revelation of the blinding factor for the input,
|
||||
// which shows that the input being spent is of the reissuance
|
||||
// capability type for the asset being inflated.
|
||||
uint256 assetBlindingNonce;
|
||||
|
||||
// New asset issuance:
|
||||
// This is a 32-byte nonce of no consensus-defined meaning,
|
||||
// but is used as additional entropy to the asset tag calculation.
|
||||
// This is used by higher-layer protocols for defining the
|
||||
// Ricardian contract governing the asset.
|
||||
// Existing asset reissuance:
|
||||
// The original asset entropy (combination of Ricardian contract
|
||||
// and outpoint used) which was used to generate the fixed asset
|
||||
// tag and reissuance tokens.
|
||||
uint256 assetEntropy;
|
||||
|
||||
// Both explicit and blinded issuance amounts are supported
|
||||
// (see class definition for CConfidentialValue for details).
|
||||
CConfidentialValue nAmount;
|
||||
|
||||
// If nonzero, specifies the number of asset issuance tokens to
|
||||
// generate. These tokens are made available to the outputs of the
|
||||
// generating transaction.
|
||||
CConfidentialValue nInflationKeys;
|
||||
|
||||
public:
|
||||
CAssetIssuance()
|
||||
{
|
||||
SetNull();
|
||||
}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
{
|
||||
READWRITE(assetBlindingNonce);
|
||||
READWRITE(assetEntropy);
|
||||
READWRITE(nAmount);
|
||||
READWRITE(nInflationKeys);
|
||||
}
|
||||
|
||||
void SetNull() { nAmount.SetNull(); nInflationKeys.SetNull(); }
|
||||
bool IsNull() const { return (nAmount.IsNull() && nInflationKeys.IsNull()); }
|
||||
|
||||
friend bool operator==(const CAssetIssuance& a, const CAssetIssuance& b)
|
||||
{
|
||||
return a.assetBlindingNonce == b.assetBlindingNonce &&
|
||||
a.assetEntropy == b.assetEntropy &&
|
||||
a.nAmount == b.nAmount &&
|
||||
a.nInflationKeys == b.nInflationKeys;
|
||||
}
|
||||
|
||||
friend bool operator!=(const CAssetIssuance& a, const CAssetIssuance& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
std::string ToString() const;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_PRIMITIVES_CONFIDENTIAL_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue