MWEB: Add StealthAddress to CTxDestination and add pegin and hogex script consts & logic
This commit is contained in:
parent
9d1f530a5f
commit
d8e940f301
@ -132,6 +132,7 @@ public:
|
||||
base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x88, 0xAD, 0xE4};
|
||||
|
||||
bech32_hrp = "ltc";
|
||||
mweb_hrp = "ltcmweb";
|
||||
|
||||
vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main));
|
||||
|
||||
@ -236,6 +237,7 @@ public:
|
||||
base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94};
|
||||
|
||||
bech32_hrp = "tltc";
|
||||
mweb_hrp = "tmweb";
|
||||
|
||||
vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test));
|
||||
|
||||
@ -341,6 +343,7 @@ public:
|
||||
base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94};
|
||||
|
||||
bech32_hrp = "rltc";
|
||||
mweb_hrp = "tmweb";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -89,6 +89,7 @@ public:
|
||||
const std::vector<std::string>& DNSSeeds() const { return vSeeds; }
|
||||
const std::vector<unsigned char>& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; }
|
||||
const std::string& Bech32HRP() const { return bech32_hrp; }
|
||||
const std::string& MWEB_HRP() const { return mweb_hrp; }
|
||||
const std::vector<SeedSpec6>& FixedSeeds() const { return vFixedSeeds; }
|
||||
const CCheckpointData& Checkpoints() const { return checkpointData; }
|
||||
const ChainTxData& TxData() const { return chainTxData; }
|
||||
@ -104,6 +105,7 @@ protected:
|
||||
std::vector<std::string> vSeeds;
|
||||
std::vector<unsigned char> base58Prefixes[MAX_BASE58_TYPES];
|
||||
std::string bech32_hrp;
|
||||
std::string mweb_hrp;
|
||||
std::string strNetworkID;
|
||||
CBlock genesis;
|
||||
std::vector<SeedSpec6> vFixedSeeds;
|
||||
|
||||
@ -66,6 +66,16 @@ public:
|
||||
return bech32::Encode(bech32::Encoding::BECH32M, m_params.Bech32HRP(), data);
|
||||
}
|
||||
|
||||
std::string operator()(const StealthAddress& id) const
|
||||
{
|
||||
std::vector<uint8_t> serialized = id.Serialized();
|
||||
|
||||
std::vector<uint8_t> converted = {0};
|
||||
ConvertBits<8, 5, true>([&](unsigned char c) { converted.push_back(c); }, serialized.begin(), serialized.end());
|
||||
|
||||
return bech32::Encode(bech32::Encoding::BECH32, m_params.MWEB_HRP(), converted);
|
||||
}
|
||||
|
||||
std::string operator()(const CNoDestination& no) const { return {}; }
|
||||
};
|
||||
|
||||
@ -138,6 +148,19 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
|
||||
return unk;
|
||||
}
|
||||
}
|
||||
|
||||
auto decoded = bech32::Decode(str, true);
|
||||
if (decoded.encoding == bech32::Encoding::BECH32 && decoded.hrp == params.MWEB_HRP()) {
|
||||
std::vector<uint8_t> converted;
|
||||
converted.reserve(((decoded.data.size() - 1) * 5) / 8);
|
||||
|
||||
if (ConvertBits<5, 8, false>([&](unsigned char c) { converted.push_back(c); }, decoded.data.begin() + 1, decoded.data.end())) {
|
||||
if (converted.size() == 66) {
|
||||
return StealthAddress(BigInt<33>(converted.data()), BigInt<33>(converted.data() + 33));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CNoDestination();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -154,7 +154,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIn
|
||||
const CBlockIndex* pnext;
|
||||
int confirmations = ComputeNextBlockAndDepth(tip, blockindex, pnext);
|
||||
result.pushKV("confirmations", confirmations);
|
||||
result.pushKV("strippedsize", (int)::GetSerializeSize(block, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS));
|
||||
result.pushKV("strippedsize", (int)::GetSerializeSize(block, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS | SERIALIZE_NO_MWEB));
|
||||
result.pushKV("size", (int)::GetSerializeSize(block, PROTOCOL_VERSION));
|
||||
result.pushKV("weight", (int)::GetBlockWeight(block));
|
||||
result.pushKV("height", blockindex->nHeight);
|
||||
|
||||
@ -224,6 +224,7 @@ public:
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.pushKV("isscript", false);
|
||||
obj.pushKV("iswitness", false);
|
||||
obj.pushKV("ismweb", false);
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -232,6 +233,7 @@ public:
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.pushKV("isscript", true);
|
||||
obj.pushKV("iswitness", false);
|
||||
obj.pushKV("ismweb", false);
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -242,6 +244,7 @@ public:
|
||||
obj.pushKV("iswitness", true);
|
||||
obj.pushKV("witness_version", 0);
|
||||
obj.pushKV("witness_program", HexStr(id));
|
||||
obj.pushKV("ismweb", false);
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -252,6 +255,7 @@ public:
|
||||
obj.pushKV("iswitness", true);
|
||||
obj.pushKV("witness_version", 0);
|
||||
obj.pushKV("witness_program", HexStr(id));
|
||||
obj.pushKV("ismweb", false);
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -261,6 +265,16 @@ public:
|
||||
obj.pushKV("iswitness", true);
|
||||
obj.pushKV("witness_version", (int)id.version);
|
||||
obj.pushKV("witness_program", HexStr(Span<const unsigned char>(id.program, id.length)));
|
||||
obj.pushKV("ismweb", false);
|
||||
return obj;
|
||||
}
|
||||
|
||||
UniValue operator()(const StealthAddress& id) const
|
||||
{
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.pushKV("isscript", false);
|
||||
obj.pushKV("iswitness", false);
|
||||
obj.pushKV("ismweb", true);
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
#include <script/script.h>
|
||||
|
||||
#include <mw/models/crypto/Hash.h>
|
||||
#include <util/strencodings.h>
|
||||
|
||||
#include <string>
|
||||
@ -233,6 +234,40 @@ bool CScript::IsWitnessProgram(int& version, std::vector<unsigned char>& program
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CScript::IsMWEBPegin(mw::Hash* const kernel_id) const
|
||||
{
|
||||
int version;
|
||||
std::vector<uint8_t> program;
|
||||
if (IsWitnessProgram(version, program)) {
|
||||
if (version == MWEB_PEGIN_WITNESS_VERSION && program.size() == WITNESS_MWEB_PEGIN_SIZE) {
|
||||
if (kernel_id != nullptr) {
|
||||
*kernel_id = mw::Hash(std::move(program));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CScript::IsMWEBHogAddr(mw::Hash* const header_hash) const
|
||||
{
|
||||
int version;
|
||||
std::vector<uint8_t> program;
|
||||
if (IsWitnessProgram(version, program)) {
|
||||
if (version == MWEB_HOG_ADDR_WITNESS_VERSION && program.size() == WITNESS_MWEB_HEADERHASH_SIZE) {
|
||||
if (header_hash != nullptr) {
|
||||
*header_hash = mw::Hash(std::move(program));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CScript::IsPushOnly(const_iterator pc) const
|
||||
{
|
||||
while (pc < end())
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#define BITCOIN_SCRIPT_SCRIPT_H
|
||||
|
||||
#include <crypto/common.h>
|
||||
#include <mw/models/crypto/Hash.h>
|
||||
#include <prevector.h>
|
||||
#include <serialize.h>
|
||||
|
||||
@ -19,6 +20,18 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// MWEB: Size of the witness program of the first output in HogEx transactions
|
||||
static constexpr size_t WITNESS_MWEB_HEADERHASH_SIZE = 32;
|
||||
|
||||
// MWEB: Size of the witness program for peg-in transactions
|
||||
static constexpr size_t WITNESS_MWEB_PEGIN_SIZE = 32;
|
||||
|
||||
// MWEB: Version of MWEB witness programs for HogAddr outputs
|
||||
static constexpr int MWEB_HOG_ADDR_WITNESS_VERSION = 8;
|
||||
|
||||
// MWEB: Version of MWEB witness programs for peg-in transactions
|
||||
static constexpr int MWEB_PEGIN_WITNESS_VERSION = 9;
|
||||
|
||||
// Maximum number of bytes pushable to the stack
|
||||
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520;
|
||||
|
||||
@ -528,6 +541,9 @@ public:
|
||||
bool IsPayToWitnessScriptHash() const;
|
||||
bool IsWitnessProgram(int& version, std::vector<unsigned char>& program) const;
|
||||
|
||||
bool IsMWEBPegin(mw::Hash* const kernel_id = nullptr) const;
|
||||
bool IsMWEBHogAddr(mw::Hash* const header_hash) const;
|
||||
|
||||
/** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */
|
||||
bool IsPushOnly(const_iterator pc) const;
|
||||
bool IsPushOnly() const;
|
||||
|
||||
@ -56,6 +56,8 @@ std::string GetTxnOutputType(TxoutType t)
|
||||
case TxoutType::WITNESS_V0_KEYHASH: return "witness_v0_keyhash";
|
||||
case TxoutType::WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash";
|
||||
case TxoutType::WITNESS_V1_TAPROOT: return "witness_v1_taproot";
|
||||
case TxoutType::WITNESS_MWEB_PEGIN: return "witness_mweb_pegin";
|
||||
case TxoutType::WITNESS_MWEB_HOGADDR: return "witness_mweb_hogaddr";
|
||||
case TxoutType::WITNESS_UNKNOWN: return "witness_unknown";
|
||||
} // no default case, so the compiler can warn about missing cases
|
||||
assert(false);
|
||||
@ -136,6 +138,14 @@ TxoutType Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned c
|
||||
vSolutionsRet.push_back(std::move(witnessprogram));
|
||||
return TxoutType::WITNESS_V1_TAPROOT;
|
||||
}
|
||||
if (witnessversion == MWEB_PEGIN_WITNESS_VERSION && witnessprogram.size() == WITNESS_MWEB_PEGIN_SIZE) {
|
||||
vSolutionsRet.push_back(witnessprogram);
|
||||
return TxoutType::WITNESS_MWEB_PEGIN;
|
||||
}
|
||||
if (witnessversion == MWEB_HOG_ADDR_WITNESS_VERSION && witnessprogram.size() == WITNESS_MWEB_HEADERHASH_SIZE) {
|
||||
vSolutionsRet.push_back(witnessprogram);
|
||||
return TxoutType::WITNESS_MWEB_HOGADDR;
|
||||
}
|
||||
if (witnessversion != 0) {
|
||||
vSolutionsRet.push_back(std::vector<unsigned char>{(unsigned char)witnessversion});
|
||||
vSolutionsRet.push_back(std::move(witnessprogram));
|
||||
@ -295,6 +305,11 @@ public:
|
||||
{
|
||||
return CScript() << CScript::EncodeOP_N(id.version) << std::vector<unsigned char>(id.program, id.program + id.length);
|
||||
}
|
||||
|
||||
CScript operator()(const StealthAddress& id) const
|
||||
{
|
||||
return CScript();
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@ -319,6 +334,26 @@ CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
|
||||
return script;
|
||||
}
|
||||
|
||||
CScript GetScriptForPegin(const mw::Hash& kernel_id)
|
||||
{
|
||||
CScript script;
|
||||
script << CScript::EncodeOP_N(MWEB_PEGIN_WITNESS_VERSION);
|
||||
script << kernel_id.vec();
|
||||
return script;
|
||||
}
|
||||
|
||||
bool IsValidDestination(const CTxDestination& dest) {
|
||||
return dest.which() != 0;
|
||||
}
|
||||
|
||||
bool IsPegInOutput(const CTxOutput& output)
|
||||
{
|
||||
if (!output.IsMWEB()) {
|
||||
std::vector<std::vector<uint8_t>> solutions_data;
|
||||
auto which_type = Solver(output.GetTxOut().scriptPubKey, solutions_data);
|
||||
return which_type == TxoutType::WITNESS_MWEB_PEGIN;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#ifndef BITCOIN_SCRIPT_STANDARD_H
|
||||
#define BITCOIN_SCRIPT_STANDARD_H
|
||||
|
||||
#include <mw/models/wallet/StealthAddress.h>
|
||||
#include <script/interpreter.h>
|
||||
#include <uint256.h>
|
||||
|
||||
@ -130,6 +131,8 @@ enum class TxoutType {
|
||||
WITNESS_V0_SCRIPTHASH,
|
||||
WITNESS_V0_KEYHASH,
|
||||
WITNESS_V1_TAPROOT,
|
||||
WITNESS_MWEB_PEGIN, //!< Hash of the peg-in kernel
|
||||
WITNESS_MWEB_HOGADDR, //!< HogAddr (first output of HogEx)
|
||||
WITNESS_UNKNOWN, //!< Only for Witness versions not already defined above
|
||||
};
|
||||
|
||||
@ -209,9 +212,10 @@ struct WitnessUnknown
|
||||
* * WitnessV0KeyHash: TxoutType::WITNESS_V0_KEYHASH destination (P2WPKH)
|
||||
* * WitnessUnknown: TxoutType::WITNESS_UNKNOWN/WITNESS_V1_TAPROOT destination (P2W???)
|
||||
* (taproot outputs do not require their own type as long as no wallet support exists)
|
||||
* * StealthAddress: MWEB destination
|
||||
* A CTxDestination is the internal data type encoded in a bitcoin address
|
||||
*/
|
||||
typedef boost::variant<CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown> CTxDestination;
|
||||
typedef boost::variant<CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown, StealthAddress> CTxDestination;
|
||||
|
||||
/** Check whether a CTxDestination is a CNoDestination. */
|
||||
bool IsValidDestination(const CTxDestination& dest);
|
||||
@ -265,4 +269,8 @@ CScript GetScriptForRawPubKey(const CPubKey& pubkey);
|
||||
/** Generate a multisig script. */
|
||||
CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys);
|
||||
|
||||
bool IsPegInOutput(const CTxOutput& output);
|
||||
|
||||
CScript GetScriptForPegin(const mw::Hash& kernel_id);
|
||||
|
||||
#endif // BITCOIN_SCRIPT_STANDARD_H
|
||||
|
||||
@ -1473,7 +1473,7 @@ BOOST_AUTO_TEST_CASE(script_HasValidOps)
|
||||
static CMutableTransaction TxFromHex(const std::string& str)
|
||||
{
|
||||
CMutableTransaction tx;
|
||||
VectorReader(SER_DISK, SERIALIZE_TRANSACTION_NO_WITNESS, ParseHex(str), 0) >> tx;
|
||||
VectorReader(SER_DISK, SERIALIZE_TRANSACTION_NO_WITNESS | SERIALIZE_NO_MWEB, ParseHex(str), 0) >> tx;
|
||||
return tx;
|
||||
}
|
||||
|
||||
@ -1500,6 +1500,19 @@ static CScriptWitness ScriptWitnessFromJSON(const UniValue& univalue)
|
||||
return scriptwitness;
|
||||
}
|
||||
|
||||
// MWEB: Pegin Script
|
||||
BOOST_AUTO_TEST_CASE(script_mweb_pegin)
|
||||
{
|
||||
CScript script;
|
||||
mw::Hash kernel_id = SecretKey::Random().vec();
|
||||
|
||||
script << OP_9 << kernel_id.vec();
|
||||
|
||||
mw::Hash kernel_id2;
|
||||
BOOST_CHECK(script.IsMWEBPegin(&kernel_id2));
|
||||
BOOST_CHECK(kernel_id == kernel_id2);
|
||||
}
|
||||
|
||||
#if defined(HAVE_CONSENSUS_LIB)
|
||||
|
||||
/* Test simple (successful) usage of bitcoinconsensus_verify_script */
|
||||
|
||||
@ -3735,6 +3735,14 @@ public:
|
||||
return obj;
|
||||
}
|
||||
|
||||
UniValue operator()(const StealthAddress& id) const
|
||||
{
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.pushKV("scan_pubkey", id.GetScanPubKey().ToHex());
|
||||
obj.pushKV("spend_pubkey", id.GetSpendPubKey().ToHex());
|
||||
return obj;
|
||||
}
|
||||
|
||||
UniValue operator()(const WitnessUnknown& id) const { return UniValue(UniValue::VOBJ); }
|
||||
};
|
||||
|
||||
|
||||
@ -97,6 +97,8 @@ IsMineResult IsMineInner(const LegacyScriptPubKeyMan& keystore, const CScript& s
|
||||
case TxoutType::NULL_DATA:
|
||||
case TxoutType::WITNESS_UNKNOWN:
|
||||
case TxoutType::WITNESS_V1_TAPROOT:
|
||||
case TxoutType::WITNESS_MWEB_PEGIN:
|
||||
case TxoutType::WITNESS_MWEB_HOGADDR:
|
||||
break;
|
||||
case TxoutType::PUBKEY:
|
||||
keyID = CPubKey(vSolutions[0]).GetID();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user