@@ -186,11 +186,17 @@ bool static IsLowDERSignature(const valtype &vchSig, ScriptError* serror) {
186186 return true ;
187187}
188188
189- bool static IsDefinedHashtypeSignature (const valtype &vchSig) {
189+ bool static IsDefinedHashtypeSignature (const valtype &vchSig, unsigned int flags ) {
190190 if (vchSig.size () == 0 ) {
191191 return false ;
192192 }
193193 unsigned char nHashType = vchSig[vchSig.size () - 1 ] & (~(SIGHASH_ANYONECANPAY));
194+
195+ // ELEMENTS: Only allow SIGHASH_RANGEPROOF if the flag is set (after dynafed activation).
196+ if ((flags & SCRIPT_SIGHASH_RANGEPROOF) == SCRIPT_SIGHASH_RANGEPROOF) {
197+ nHashType = nHashType & (~(SIGHASH_RANGEPROOF));
198+ }
199+
194200 if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE)
195201 return false ;
196202
@@ -216,7 +222,7 @@ bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned i
216222 } else if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && !IsLowDERSignature (vchSigCopy, serror)) {
217223 // serror is set
218224 return false ;
219- } else if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsDefinedHashtypeSignature (vchSigCopy)) {
225+ } else if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsDefinedHashtypeSignature (vchSigCopy, flags )) {
220226 return set_error (serror, SCRIPT_ERR_SIG_HASHTYPE);
221227 }
222228 return true ;
@@ -1213,7 +1219,8 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
12131219 // serror is set
12141220 return false ;
12151221 }
1216- bool fSuccess = checker.CheckSig (vchSig, vchPubKey, scriptCode, sigversion);
1222+
1223+ bool fSuccess = checker.CheckSig (vchSig, vchPubKey, scriptCode, sigversion, flags);
12171224
12181225 if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && vchSig.size ())
12191226 return set_error (serror, SCRIPT_ERR_SIG_NULLFAIL);
@@ -1291,7 +1298,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
12911298 }
12921299
12931300 // Check signature
1294- bool fOk = checker.CheckSig (vchSig, vchPubKey, scriptCode, sigversion);
1301+ bool fOk = checker.CheckSig (vchSig, vchPubKey, scriptCode, sigversion, flags );
12951302
12961303 if (fOk ) {
12971304 isig++;
@@ -1466,13 +1473,15 @@ class CTransactionSignatureSerializer
14661473 const CScript& scriptCode; // !< output script being consumed
14671474 const unsigned int nIn; // !< input index of txTo being signed
14681475 const bool fAnyoneCanPay ; // !< whether the hashtype has the SIGHASH_ANYONECANPAY flag set
1476+ const bool fRangeproof ; // !< whether the hashtype has the SIGHASH_RANGEPROOF flag set
14691477 const bool fHashSingle ; // !< whether the hashtype is SIGHASH_SINGLE
14701478 const bool fHashNone ; // !< whether the hashtype is SIGHASH_NONE
14711479
14721480public:
1473- CTransactionSignatureSerializer (const T& txToIn, const CScript& scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
1481+ CTransactionSignatureSerializer (const T& txToIn, const CScript& scriptCodeIn, unsigned int nInIn, int nHashTypeIn, unsigned int flags ) :
14741482 txTo (txToIn), scriptCode(scriptCodeIn), nIn(nInIn),
14751483 fAnyoneCanPay (!!(nHashTypeIn & SIGHASH_ANYONECANPAY)),
1484+ fRangeproof (!!(flags & SCRIPT_SIGHASH_RANGEPROOF) && !!(nHashTypeIn & SIGHASH_RANGEPROOF)),
14761485 fHashSingle ((nHashTypeIn & 0x1f ) == SIGHASH_SINGLE),
14771486 fHashNone ((nHashTypeIn & 0x1f ) == SIGHASH_NONE) {}
14781487
@@ -1529,11 +1538,23 @@ class CTransactionSignatureSerializer
15291538 /* * Serialize an output of txTo */
15301539 template <typename S>
15311540 void SerializeOutput (S &s, unsigned int nOutput) const {
1532- if (fHashSingle && nOutput != nIn)
1541+ if (fHashSingle && nOutput != nIn) {
15331542 // Do not lock-in the txout payee at other indices as txin
15341543 ::Serialize (s, CTxOut());
1535- else
1544+ } else {
15361545 ::Serialize (s, txTo.vout[nOutput]);
1546+
1547+ // Serialize rangeproof
1548+ if (fRangeproof ) {
1549+ if (nOutput < txTo.witness .vtxoutwit .size ()) {
1550+ ::Serialize (s, txTo.witness.vtxoutwit[nOutput].vchRangeproof);
1551+ ::Serialize (s, txTo.witness.vtxoutwit[nOutput].vchSurjectionproof);
1552+ } else {
1553+ ::Serialize (s, (unsigned char ) 0);
1554+ ::Serialize (s, (unsigned char ) 0);
1555+ }
1556+ }
1557+ }
15371558 }
15381559
15391560 /* * Serialize txTo */
@@ -1599,6 +1620,21 @@ uint256 GetOutputsHash(const T& txTo)
15991620 return ss.GetHash ();
16001621}
16011622
1623+ template <class T >
1624+ uint256 GetRangeproofsHash (const T& txTo) {
1625+ CHashWriter ss (SER_GETHASH, 0 );
1626+ for (size_t i = 0 ; i < txTo.vout .size (); i++) {
1627+ if (i < txTo.witness .vtxoutwit .size ()) {
1628+ ss << txTo.witness .vtxoutwit [i].vchRangeproof ;
1629+ ss << txTo.witness .vtxoutwit [i].vchSurjectionproof ;
1630+ } else {
1631+ ss << (unsigned char ) 0 ;
1632+ ss << (unsigned char ) 0 ;
1633+ }
1634+ }
1635+ return ss.GetHash ();
1636+ }
1637+
16021638} // namespace
16031639
16041640template <class T >
@@ -1610,6 +1646,7 @@ PrecomputedTransactionData::PrecomputedTransactionData(const T& txTo)
16101646 hashSequence = GetSequenceHash (txTo);
16111647 hashIssuance = GetIssuanceHash (txTo);
16121648 hashOutputs = GetOutputsHash (txTo);
1649+ hashRangeproofs = GetRangeproofsHash (txTo);
16131650 ready = true ;
16141651 }
16151652}
@@ -1619,7 +1656,7 @@ template PrecomputedTransactionData::PrecomputedTransactionData(const CTransacti
16191656template PrecomputedTransactionData::PrecomputedTransactionData(const CMutableTransaction& txTo);
16201657
16211658template <class T >
1622- uint256 SignatureHash (const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const CConfidentialValue& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
1659+ uint256 SignatureHash (const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const CConfidentialValue& amount, SigVersion sigversion, unsigned int flags, const PrecomputedTransactionData* cache)
16231660{
16241661 assert (nIn < txTo.vin .size ());
16251662
@@ -1628,7 +1665,9 @@ uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn
16281665 uint256 hashSequence;
16291666 uint256 hashIssuance;
16301667 uint256 hashOutputs;
1668+ uint256 hashRangeproofs;
16311669 const bool cacheready = cache && cache->ready ;
1670+ bool fRangeproof = !!(flags & SCRIPT_SIGHASH_RANGEPROOF) && !!(nHashType & SIGHASH_RANGEPROOF);
16321671
16331672 if (!(nHashType & SIGHASH_ANYONECANPAY)) {
16341673 hashPrevouts = cacheready ? cache->hashPrevouts : GetPrevoutHash (txTo);
@@ -1644,10 +1683,26 @@ uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn
16441683
16451684 if ((nHashType & 0x1f ) != SIGHASH_SINGLE && (nHashType & 0x1f ) != SIGHASH_NONE) {
16461685 hashOutputs = cacheready ? cache->hashOutputs : GetOutputsHash (txTo);
1686+
1687+ if (fRangeproof ) {
1688+ hashRangeproofs = cacheready ? cache->hashRangeproofs : GetRangeproofsHash (txTo);
1689+ }
16471690 } else if ((nHashType & 0x1f ) == SIGHASH_SINGLE && nIn < txTo.vout .size ()) {
16481691 CHashWriter ss (SER_GETHASH, 0 );
16491692 ss << txTo.vout [nIn];
16501693 hashOutputs = ss.GetHash ();
1694+
1695+ if (fRangeproof ) {
1696+ CHashWriter ss (SER_GETHASH, 0 );
1697+ if (nIn < txTo.witness .vtxoutwit .size ()) {
1698+ ss << txTo.witness .vtxoutwit [nIn].vchRangeproof ;
1699+ ss << txTo.witness .vtxoutwit [nIn].vchSurjectionproof ;
1700+ } else {
1701+ ss << (unsigned char ) 0 ;
1702+ ss << (unsigned char ) 0 ;
1703+ }
1704+ hashRangeproofs = ss.GetHash ();
1705+ }
16511706 }
16521707
16531708 CHashWriter ss (SER_GETHASH, 0 );
@@ -1676,6 +1731,11 @@ uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn
16761731 }
16771732 // Outputs (none/one/all, depending on flags)
16781733 ss << hashOutputs;
1734+ if (fRangeproof ) {
1735+ // This addition must be conditional because it was added after
1736+ // the segwit sighash was specified.
1737+ ss << hashRangeproofs;
1738+ }
16791739 // Locktime
16801740 ss << txTo.nLockTime ;
16811741 // Sighash type
@@ -1695,7 +1755,7 @@ uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn
16951755 }
16961756
16971757 // Wrapper to serialize only the necessary parts of the transaction being signed
1698- CTransactionSignatureSerializer<T> txTmp (txTo, scriptCode, nIn, nHashType);
1758+ CTransactionSignatureSerializer<T> txTmp (txTo, scriptCode, nIn, nHashType, flags );
16991759
17001760 // Serialize and hash
17011761 CHashWriter ss (SER_GETHASH, 0 );
@@ -1710,7 +1770,7 @@ bool GenericTransactionSignatureChecker<T>::VerifySignature(const std::vector<un
17101770}
17111771
17121772template <class T >
1713- bool GenericTransactionSignatureChecker<T>::CheckSig(const std::vector<unsigned char >& vchSigIn, const std::vector<unsigned char >& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
1773+ bool GenericTransactionSignatureChecker<T>::CheckSig(const std::vector<unsigned char >& vchSigIn, const std::vector<unsigned char >& vchPubKey, const CScript& scriptCode, SigVersion sigversion, unsigned int flags ) const
17141774{
17151775 CPubKey pubkey (vchPubKey);
17161776 if (!pubkey.IsValid ())
@@ -1723,7 +1783,7 @@ bool GenericTransactionSignatureChecker<T>::CheckSig(const std::vector<unsigned
17231783 int nHashType = vchSig.back ();
17241784 vchSig.pop_back ();
17251785
1726- uint256 sighash = SignatureHash (scriptCode, *txTo, nIn, nHashType, amount, sigversion, this ->txdata );
1786+ uint256 sighash = SignatureHash (scriptCode, *txTo, nIn, nHashType, amount, sigversion, flags, this ->txdata );
17271787
17281788 if (!VerifySignature (vchSig, pubkey, sighash))
17291789 return false ;
0 commit comments