Line data Source code
1 : /** 2 : * @file CoinSpend.cpp 3 : * 4 : * @brief CoinSpend class for the Zerocoin library. 5 : * 6 : * @author Ian Miers, Christina Garman and Matthew Green 7 : * @date June 2013 8 : * 9 : * @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green 10 : * @license This project is released under the MIT license. 11 : **/ 12 : // Copyright (c) 2017-2021 The PIVX Core developers 13 : 14 : #include "CoinSpend.h" 15 : #include <iostream> 16 : #include <sstream> 17 : 18 : namespace libzerocoin 19 : { 20 : 21 0 : const uint256 CoinSpend::signatureHash() const 22 : { 23 0 : CHashWriter h(0, 0); 24 0 : h << serialCommitmentToCoinValue << accCommitmentToCoinValue << commitmentPoK << accumulatorPoK << ptxHash 25 0 : << coinSerialNumber << accChecksum << denomination; 26 : 27 0 : if (version >= PUBKEY_VERSION) 28 0 : h << spendType; 29 : 30 0 : return h.GetHash(); 31 : } 32 : 33 0 : std::string CoinSpend::ToString() const 34 : { 35 0 : std::stringstream ss; 36 0 : ss << "CoinSpend:\n version=" << (int)version << " signatureHash=" << signatureHash().GetHex() << " spendtype=" << spendType << "\n"; 37 0 : return ss.str(); 38 : } 39 : 40 0 : bool CoinSpend::HasValidSerial(ZerocoinParams* params) const 41 : { 42 0 : return IsValidSerial(params, coinSerialNumber); 43 : } 44 : 45 : //Additional verification layer that requires the spend be signed by the private key associated with the serial 46 0 : bool CoinSpend::HasValidSignature() const 47 : { 48 0 : const int coinVersion = getCoinVersion(); 49 : //No private key for V1 50 0 : if (coinVersion < PUBKEY_VERSION) 51 : return true; 52 : 53 0 : try { 54 : //V2 serial requires that the signature hash be signed by the public key associated with the serial 55 0 : arith_uint256 hashedPubkey = UintToArith256(Hash(pubkey.begin(), pubkey.end())) >> V2_BITSHIFT; 56 0 : if (hashedPubkey != GetAdjustedSerial(coinSerialNumber).getuint256()) { 57 : //cout << "CoinSpend::HasValidSignature() hashedpubkey is not equal to the serial!\n"; 58 0 : return false; 59 : } 60 0 : } catch (const std::range_error& e) { 61 : //std::cout << "HasValidSignature() error: " << e.what() << std::endl; 62 0 : throw InvalidSerialException("Serial longer than 256 bits"); 63 : } 64 : 65 0 : return pubkey.Verify(signatureHash(), vchSig); 66 : } 67 : 68 0 : CBigNum CoinSpend::CalculateValidSerial(ZerocoinParams* params) 69 : { 70 0 : CBigNum bnSerial = coinSerialNumber; 71 0 : bnSerial = bnSerial % params->coinCommitmentGroup.groupOrder; 72 0 : return bnSerial; 73 : } 74 : 75 0 : std::vector<unsigned char> CoinSpend::ParseSerial(CDataStream& s) { 76 0 : unsigned int nSize = ReadCompactSize(s); 77 0 : s.movePos(nSize); 78 0 : nSize = ReadCompactSize(s); 79 0 : s.movePos(nSize); 80 0 : CBigNum coinSerialNumber; 81 0 : s >> coinSerialNumber; 82 0 : return coinSerialNumber.getvch(); 83 : } 84 : 85 0 : void CoinSpend::setPubKey(CPubKey pkey, bool fUpdateSerial) { 86 0 : this->pubkey = pkey; 87 0 : if (fUpdateSerial) { 88 0 : this->coinSerialNumber = libzerocoin::ExtractSerialFromPubKey(this->pubkey); 89 : } 90 0 : } 91 : 92 : } /* namespace libzerocoin */