diff --git a/src/Makefile.am b/src/Makefile.am index 400f6436d689..971da21ddc55 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -292,6 +292,7 @@ BITCOIN_CORE_H = \ wallet/crypter.h \ wallet/db.h \ wallet/fees.h \ + wallet/keypool.h \ wallet/psbtwallet.h \ wallet/rpcwallet.h \ wallet/wallet.h \ @@ -440,6 +441,7 @@ libdash_wallet_a_SOURCES = \ wallet/db.cpp \ wallet/fees.cpp \ wallet/init.cpp \ + wallet/keypool.cpp \ wallet/psbtwallet.cpp \ wallet/rpcdump.cpp \ wallet/rpcwallet.cpp \ diff --git a/src/bls/bls.cpp b/src/bls/bls.cpp index 47aeb8e3f9d1..44a0fb3a082a 100644 --- a/src/bls/bls.cpp +++ b/src/bls/bls.cpp @@ -21,7 +21,14 @@ static const std::unique_ptr& Scheme(const bool fLegacy) return fLegacy ? pSchemeLegacy : pScheme; } -CBLSId::CBLSId(const uint256& nHash) : CBLSWrapper() +CBLSId::CBLSId(const uint256& nHash) : CBLSWrapper, BLS_CURVE_ID_SIZE, CBLSId>() +{ + impl = nHash; + fValid = true; + cachedHash.SetNull(); +} + +CBLSKeyID::CBLSKeyID(const uint160& nHash) : CBLSWrapper, BLS_CURVE_ID_SIZE, CBLSKeyID>() { impl = nHash; fValid = true; @@ -393,3 +400,57 @@ bool BLSInit() #endif return true; } + +bool CSecretKey::Load(const std::vector >& privkey, const CPublicKey& vchPubKey, bool fSkipCheck) +{ + CPublicKey pkTmp; + std::vector vchTmp; + vchTmp.assign(privkey.begin(), privkey.end()); + pkTmp.SetByteVector(vchTmp); + SetByteVector(vchTmp); + return fSkipCheck ? IsValid() : IsValid() && vchPubKey == pkTmp; +} + +bool CSecretKey::Sign(const uint256& hash, std::vector& vchSig) const +{ + CBLSSignature sig = Sign(hash); + if (sig.IsValid()) { + vchSig = sig.ToByteVector(); + return true; + } + return false; +} + +bool CSecretKey::VerifyPubKey(const CPublicKey& vchPubKey) const +{ + CPublicKey vchTmp; + vchTmp.SetByteVector(ToByteVector()); + return vchPubKey == vchTmp; +} + +CBLSKeyID CPublicKey::GetID() const +{ + return CBLSKeyID(Hash160(ToByteVector())); +} + +uint256 CPublicKey::GetHash() const +{ + return uint256(ToByteVector()); +} + +bool CPublicKey::Verify(const uint256& hash, const std::vector& vchSig) const +{ + return CBLSSignature(vchSig, false).VerifyInsecure(*this, hash); +} + +std::vector > CSecretKey::GetPrivKey() const +{ + return std::vector >(ToByteVector().begin(), ToByteVector().end()); +} + +CPublicKey CSecretKey::GetPubKey() const +{ + CPublicKey vchPubKey; + vchPubKey.SetByteVector(ToByteVector()); + return vchPubKey; +} \ No newline at end of file diff --git a/src/bls/bls.h b/src/bls/bls.h index 94bcb41f95f6..bc4005e21cef 100644 --- a/src/bls/bls.h +++ b/src/bls/bls.h @@ -10,6 +10,8 @@ #include #include +#include + // bls-dash uses relic, which may define DEBUG and ERROR, which leads to many warnings in some build setups #undef ERROR #undef DEBUG @@ -32,6 +34,8 @@ static const bool fLegacyDefault{true}; #define BLS_CURVE_PUBKEY_SIZE 48 #define BLS_CURVE_SIG_SIZE 96 +class CPublicKey; +class CSecretKey; class CBLSSignature; class CBLSPublicKey; @@ -42,10 +46,9 @@ class CBLSWrapper friend class CBLSPublicKey; friend class CBLSSignature; - bool fLegacy; - protected: ImplType impl; + bool fLegacy = fLegacyDefault; bool fValid{false}; mutable uint256 cachedHash; @@ -152,6 +155,12 @@ class CBLSWrapper return IsValid(); } + //! CKey-like read only interface to access byte vector + unsigned int size() const { return (new std::vector(ToByteVector()))->size(); } + const unsigned char* begin() const { return (new std::vector(ToByteVector()))->data(); } + const unsigned char* end() const { return (new std::vector(ToByteVector()))->data() + size(); } + const unsigned char& operator[](unsigned int pos) const { return (new std::vector(ToByteVector()))->data()[pos]; } + public: inline void Serialize(CSizeComputer& s) const { @@ -193,12 +202,13 @@ class CBLSWrapper } }; -struct CBLSIdImplicit : public uint256 +template +struct CBLSIdImplicit : public T1 { CBLSIdImplicit() = default; - CBLSIdImplicit(const uint256& id) + CBLSIdImplicit(const T1& id) { - memcpy(begin(), id.begin(), sizeof(uint256)); + memcpy(this->begin(), id.begin(), sizeof(T1)); } static CBLSIdImplicit FromBytes(const uint8_t* buffer, const bool fLegacy = false) { @@ -208,11 +218,11 @@ struct CBLSIdImplicit : public uint256 } std::vector Serialize(const bool fLegacy = false) const { - return {begin(), end()}; + return {this->begin(), this->end()}; } }; -class CBLSId : public CBLSWrapper +class CBLSId : public CBLSWrapper, BLS_CURVE_ID_SIZE, CBLSId> { public: using CBLSWrapper::operator=; @@ -224,6 +234,20 @@ class CBLSId : public CBLSWrapper explicit CBLSId(const uint256& nHash); }; +class CBLSKeyID : public CBLSWrapper, BLS_CURVE_ID_SIZE, CBLSKeyID> +{ +public: + using CBLSWrapper::operator=; + using CBLSWrapper::operator==; + using CBLSWrapper::operator!=; + using CBLSWrapper::CBLSWrapper; + + CBLSKeyID() = default; + explicit CBLSKeyID(const uint160& nHash); + + friend inline bool operator<(const CBLSKeyID& a, const CBLSKeyID& b) { return a.impl.Compare(b.impl) < 0; } +}; + class CBLSSecretKey : public CBLSWrapper { public: @@ -248,6 +272,25 @@ class CBLSSecretKey : public CBLSWrapper > GetPrivKey() const; + CPublicKey GetPubKey() const; + + bool Load(const std::vector >& privkey, const CPublicKey& vchPubKey, bool fSkipCheck); + bool Sign(const uint256& hash, std::vector& vchSig) const; + bool VerifyPubKey(const CPublicKey& vchPubKey) const; +}; + class CBLSPublicKey : public CBLSWrapper { friend class CBLSSecretKey; @@ -269,6 +312,19 @@ class CBLSPublicKey : public CBLSWrapper& vchSig) const; +}; + class CBLSSignature : public CBLSWrapper { friend class CBLSSecretKey; diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 95a0bf284823..0b5c2be789f5 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -443,6 +443,8 @@ class CMainParams : public CChainParams { base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,16); // Dash private keys start with '7' or 'X' base58Prefixes[SECRET_KEY] = std::vector(1,204); + // Dash BLS addresses start with 'D' + base58Prefixes[PUBKEY_ADDRESS_BLS] = std::vector(1,30); // Dash BIP32 pubkeys start with 'xpub' (Bitcoin defaults) base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x88, 0xB2, 0x1E}; // Dash BIP32 prvkeys start with 'xprv' (Bitcoin defaults) @@ -645,6 +647,8 @@ class CTestNetParams : public CChainParams { base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,19); // Testnet private keys start with '9' or 'c' (Bitcoin defaults) base58Prefixes[SECRET_KEY] = std::vector(1,239); + // Testnet Dash BLS addresses start with '5' + base58Prefixes[PUBKEY_ADDRESS_BLS] = std::vector(1,10); // Testnet Dash BIP32 pubkeys start with 'tpub' (Bitcoin defaults) base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; // Testnet Dash BIP32 prvkeys start with 'tprv' (Bitcoin defaults) @@ -827,6 +831,8 @@ class CDevNetParams : public CChainParams { base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,19); // Testnet private keys start with '9' or 'c' (Bitcoin defaults) base58Prefixes[SECRET_KEY] = std::vector(1,239); + // Testnet Dash BLS addresses start with '5' + base58Prefixes[PUBKEY_ADDRESS_BLS] = std::vector(1,10); // Testnet Dash BIP32 pubkeys start with 'tpub' (Bitcoin defaults) base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; // Testnet Dash BIP32 prvkeys start with 'tprv' (Bitcoin defaults) @@ -1007,6 +1013,8 @@ class CRegTestParams : public CChainParams { base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,19); // Regtest private keys start with '9' or 'c' (Bitcoin defaults) base58Prefixes[SECRET_KEY] = std::vector(1,239); + // Regtest Dash BLS addresses start with '5' + base58Prefixes[PUBKEY_ADDRESS_BLS] = std::vector(1,10); // Regtest Dash BIP32 pubkeys start with 'tpub' (Bitcoin defaults) base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; // Regtest Dash BIP32 prvkeys start with 'tprv' (Bitcoin defaults) diff --git a/src/chainparams.h b/src/chainparams.h index ce30aaad77c2..bbda337322a6 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -53,6 +53,7 @@ class CChainParams SECRET_KEY, // BIP16 EXT_PUBLIC_KEY, // BIP32 EXT_SECRET_KEY, // BIP32 + PUBKEY_ADDRESS_BLS, MAX_BASE58_TYPES }; diff --git a/src/coinjoin/coinjoin-client.cpp b/src/coinjoin/coinjoin-client.cpp index 6832e00c20d3..5d3395c83f52 100644 --- a/src/coinjoin/coinjoin-client.cpp +++ b/src/coinjoin/coinjoin-client.cpp @@ -1540,7 +1540,7 @@ bool CCoinJoinClientSession::CreateCollateralTransaction(CMutableTransaction& tx // make our change address CScript scriptChange; CPubKey vchPubKey; - CReserveKey reservekey(&mixingWallet); + CReserveKey reservekey(&mixingWallet); bool success = reservekey.GetReservedKey(vchPubKey, true); assert(success); // should never fail, as we just unlocked scriptChange = GetScriptForDestination(vchPubKey.GetID()); diff --git a/src/coinjoin/coinjoin-util.h b/src/coinjoin/coinjoin-util.h index ac536030eb46..860059bfdce4 100644 --- a/src/coinjoin/coinjoin-util.h +++ b/src/coinjoin/coinjoin-util.h @@ -12,7 +12,7 @@ class CTransactionBuilder; class CKeyHolder { private: - CReserveKey reserveKey; + CReserveKey reserveKey; CPubKey pubKey; public: @@ -46,7 +46,7 @@ class CTransactionBuilderOutput /// Used for amount updates CTransactionBuilder* pTxBuilder{nullptr}; /// Reserve key where the amount of this output will end up - CReserveKey key; + CReserveKey key; /// Amount this output will receive CAmount nAmount{0}; /// ScriptPubKey of this output @@ -82,7 +82,7 @@ class CTransactionBuilder /// Dummy since we anyway use tallyItem's destination as change destination in coincontrol. /// Its a member just to make sure ReturnKey can be called in destructor just in case it gets generated/kept /// somewhere in CWallet code. - CReserveKey dummyReserveKey; + CReserveKey dummyReserveKey; /// Contains all utxos available to generate this transactions. They are all from the same address. CompactTallyItem tallyItem; /// Contains the number of bytes required for a transaction with only the inputs of tallyItems, no outputs diff --git a/src/compressor.cpp b/src/compressor.cpp index b003a86ce7a4..5a4087c79924 100644 --- a/src/compressor.cpp +++ b/src/compressor.cpp @@ -5,6 +5,7 @@ #include +#include #include #include #include