@@ -1092,6 +1092,12 @@ const unsigned char PIVX_SEQUENCE_HASH_PERSONALIZATION[crypto_generichash_blake2
10921092 {' P' ,' I' ,' V' ,' X' ,' S' ,' e' ,' q' ,' u' ,' e' ,' n' ,' c' ,' H' ,' a' ,' s' ,' h' };
10931093const unsigned char PIVX_OUTPUTS_HASH_PERSONALIZATION[crypto_generichash_blake2b_PERSONALBYTES] =
10941094 {' P' ,' I' ,' V' ,' X' ,' O' ,' u' ,' t' ,' p' ,' u' ,' t' ,' s' ,' H' ,' a' ,' s' ,' h' };
1095+ const unsigned char PIVX_SHIELDED_SPENDS_HASH_PERSONALIZATION[crypto_generichash_blake2b_PERSONALBYTES] =
1096+ {' P' ,' I' ,' V' ,' X' ,' S' ,' S' ,' p' ,' e' ,' n' ,' d' ,' s' ,' H' ,' a' ,' s' ,' h' };
1097+ const unsigned char PIVX_SHIELDED_OUTPUTS_HASH_PERSONALIZATION[crypto_generichash_blake2b_PERSONALBYTES] =
1098+ {' P' ,' I' ,' V' ,' X' ,' S' ,' O' ,' u' ,' t' ,' p' ,' u' ,' t' ,' H' ,' a' ,' s' ,' h' };
1099+
1100+
10951101
10961102uint256 GetPrevoutHash (const CTransaction& txTo) {
10971103 CBLAKE2bWriter ss (SER_GETHASH, 0 , PIVX_PREVOUTS_HASH_PERSONALIZATION);
@@ -1117,13 +1123,39 @@ uint256 GetOutputsHash(const CTransaction& txTo) {
11171123 return ss.GetHash ();
11181124}
11191125
1126+ uint256 GetShieldedSpendsHash (const CTransaction& txTo) {
1127+ CBLAKE2bWriter ss (SER_GETHASH, 0 , PIVX_SHIELDED_SPENDS_HASH_PERSONALIZATION);
1128+ auto sapData = txTo.sapData ;
1129+ for (const auto & n : sapData->vShieldedSpend ) {
1130+ ss << n.cv ;
1131+ ss << n.anchor ;
1132+ ss << n.nullifier ;
1133+ ss << n.rk ;
1134+ ss << n.zkproof ;
1135+ }
1136+ return ss.GetHash ();
1137+ }
1138+
1139+ uint256 GetShieldedOutputsHash (const CTransaction& txTo) {
1140+ CBLAKE2bWriter ss (SER_GETHASH, 0 , PIVX_SHIELDED_OUTPUTS_HASH_PERSONALIZATION);
1141+ auto sapData = txTo.sapData ;
1142+ for (const auto & n : sapData->vShieldedOutput ) {
1143+ ss << n;
1144+ }
1145+ return ss.GetHash ();
1146+ }
1147+
11201148} // anon namespace
11211149
11221150PrecomputedTransactionData::PrecomputedTransactionData (const CTransaction& txTo)
11231151{
11241152 hashPrevouts = GetPrevoutHash (txTo);
11251153 hashSequence = GetSequenceHash (txTo);
11261154 hashOutputs = GetOutputsHash (txTo);
1155+ if (txTo.sapData ) {
1156+ hashShieldedSpends = GetShieldedSpendsHash (txTo);
1157+ hashShieldedOutputs = GetShieldedOutputsHash (txTo);
1158+ }
11271159}
11281160
11291161uint256 SignatureHash (const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
@@ -1138,6 +1170,9 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
11381170 uint256 hashPrevouts;
11391171 uint256 hashSequence;
11401172 uint256 hashOutputs;
1173+ uint256 hashShieldedSpends;
1174+ uint256 hashShieldedOutputs;
1175+ bool hasSapData = false ;
11411176
11421177 if (!(nHashType & SIGHASH_ANYONECANPAY)) {
11431178 hashPrevouts = cache ? cache->hashPrevouts : GetPrevoutHash (txTo);
@@ -1155,6 +1190,18 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
11551190 hashOutputs = ss.GetHash ();
11561191 }
11571192
1193+ if (txTo.sapData ) {
1194+ if (!txTo.sapData ->vShieldedSpend .empty ()) {
1195+ hashShieldedSpends = cache ? cache->hashShieldedSpends : GetShieldedSpendsHash (txTo);
1196+ hasSapData = true ;
1197+ }
1198+
1199+ if (!txTo.sapData ->vShieldedOutput .empty ()) {
1200+ hashShieldedOutputs = cache ? cache->hashShieldedOutputs : GetShieldedOutputsHash (txTo);
1201+ hasSapData = true ;
1202+ }
1203+ }
1204+
11581205 // todo: complete branch id with the active network upgrade
11591206 uint32_t leConsensusBranchId = htole32 (0 );
11601207 unsigned char personalization[16 ] = {};
@@ -1167,15 +1214,26 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
11671214 // Input prevouts/nSequence (none/all, depending on flags)
11681215 ss << hashPrevouts;
11691216 ss << hashSequence;
1217+ // Outputs (none/one/all, depending on flags)
1218+ ss << hashOutputs;
1219+
1220+ if (hasSapData) {
1221+ // Spend descriptions
1222+ ss << hashShieldedSpends;
1223+ // Output descriptions
1224+ ss << hashShieldedOutputs;
1225+ // Sapling value balance
1226+ ss << txTo.sapData ->valueBalance ;
1227+ }
1228+
11701229 // The input being signed (replacing the scriptSig with scriptCode + amount)
11711230 // The prevout may already be contained in hashPrevout, and the nSequence
11721231 // may already be contained in hashSequence.
11731232 ss << txTo.vin [nIn].prevout ;
11741233 ss << static_cast <const CScriptBase&>(scriptCode);
11751234 ss << amount;
11761235 ss << txTo.vin [nIn].nSequence ;
1177- // Outputs (none/one/all, depending on flags)
1178- ss << hashOutputs;
1236+
11791237 // Locktime
11801238 ss << txTo.nLockTime ;
11811239 // Sighash type
0 commit comments