diff --git a/src/main.cpp b/src/main.cpp index 2de5a25dd7f..7d0d52424ed 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1434,6 +1434,7 @@ bool CheckTransaction(uint32_t tiptime,const CTransaction& tx, CValidationState } } +// ARRR notary exception int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime) // from ac_private chains only { int32_t season = getacseason(tiptime); @@ -1460,7 +1461,7 @@ int32_t komodo_acpublic(uint32_t tiptime); bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransaction& tx, CValidationState &state) { // Basic checks that don't depend on any context - int32_t invalid_private_taddr=0,z_z=0,z_t=0,t_z=0,acpublic = komodo_acpublic(tiptime); + int32_t invalid_private_taddr=0,z_z=0,z_t=0,t_z=0,acpublic = komodo_acpublic(tiptime), current_season = getacseason(tiptime); /** * Previously: * 1. The consensus rule below was: @@ -1571,9 +1572,18 @@ bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransactio } if ( ASSETCHAINS_PRIVATE != 0 && invalid_private_taddr != 0 && tx.vShieldedSpend.empty() == 0 ) { - return state.DoS(100, error("CheckTransaction(): this is a private chain, no sapling -> taddr"), - REJECT_INVALID, "bad-txns-acprivate-chain"); + if ( !( current_season > 5 && + tx.vin.size() == 0 && + tx.vout.size() == 2 && + tx.vout[0].scriptPubKey.IsPayToScriptHash() && + tx.vout[0].scriptPubKey.IsRedeemScriptReveal(tx.vout[1].scriptPubKey) )) { + return state.DoS(100, error("CheckTransaction(): this is a private chain, no sapling -> taddr"), + REJECT_INVALID, "bad-txns-acprivate-chain"); + } else { + invalid_private_taddr = false; + } } + // Check for overflow valueBalance if (tx.valueBalance > MAX_MONEY || tx.valueBalance < -MAX_MONEY) { return state.DoS(100, error("CheckTransaction(): abs(tx.valueBalance) too large"), @@ -5160,7 +5170,7 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C { int32_t notaryid; int32_t special = komodo_chosennotary(¬aryid,height,pubkey33,tiptime); - if (notaryid > 0) { + if (notaryid > 0 || ( notaryid == 0 && height > nS5HardforkHeight ) ) { CScript merkleroot = CScript(); CBlock blockcopy = block; // block shouldn't be changed below, so let's make it's copy CBlock *pblockcopy = (CBlock *)&blockcopy; diff --git a/src/script/script.cpp b/src/script/script.cpp index 69e340758e5..0df33bf2cff 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -24,6 +24,7 @@ #include "utilstrencodings.h" #include "script/cc.h" #include "cc/eval.h" +#include "standard.h" #include "cryptoconditions/include/cryptoconditions.h" using namespace std; @@ -255,6 +256,93 @@ bool CScript::IsPayToScriptHash() const (*this)[22] == OP_EQUAL); } +bool CScript::IsRedeemScriptReveal(CScript scriptpubkey) const{ + CScript check_spk, redeemScript = scriptpubkey; + if ( + // these magic numbers correspond to a typical(as of May 2021) atomicdex HLTC + redeemScript.size() == 110 && + redeemScript[0] == OP_RETURN && + redeemScript[3] == OP_IF && + redeemScript[9] == OP_NOP2 && + redeemScript[10] == OP_DROP && + redeemScript[45] == OP_CHECKSIG && + redeemScript[46] == OP_ELSE && + redeemScript[47] == OP_SIZE && + redeemScript[48] == 0x01 && + redeemScript[49] == 0x20 && + redeemScript[50] == OP_EQUALVERIFY && + redeemScript[51] == OP_HASH160 && + redeemScript[73] == OP_EQUALVERIFY && + redeemScript[108] == OP_CHECKSIG && + redeemScript[109] == OP_ENDIF + ) { + // Drop the OP_RETURN and OP_PUSHDATA1 + byte + redeemScript.erase(redeemScript.begin(),redeemScript.begin()+3 ); + check_spk << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; + return (check_spk == (*this)); + } + + if ( + /* + these magic numbers correspond to: + + OP_IF 32_bitlocktime OP_CHECKLOCKTIMEVERIFY OP_DROP pubkey OP_CHECKSIG + OP_ELSE OP_SIZE 0x20 OP_EQUALVERIFY + OP_SHA256 0000000000000000000000000000000000000000000000000000000000000000 OP_EQUALVERIFY pubkey OP_CHECKSIG OP_ENDIF + + This is neccesary for coins that do not support ripemd160. + It is a typical HLTC with OP_SHA256 instead of OP_HASH160 + */ + redeemScript.size() == 122 && + redeemScript[0] == OP_RETURN && + redeemScript[3] == OP_IF && + redeemScript[9] == OP_NOP2 && + redeemScript[10] == OP_DROP && + redeemScript[45] == OP_CHECKSIG && + redeemScript[46] == OP_ELSE && + redeemScript[47] == OP_SIZE && + redeemScript[48] == 0x01 && + redeemScript[49] == 0x20 && + redeemScript[50] == OP_EQUALVERIFY && + ( redeemScript[51] == OP_SHA256 || redeemScript[51] == OP_HASH256 ) && + redeemScript[85] == OP_EQUALVERIFY && + redeemScript[120] == OP_CHECKSIG && + redeemScript[121] == OP_ENDIF + ) { + // Drop the OP_RETURN and OP_PUSHDATA1 + byte + redeemScript.erase(redeemScript.begin(),redeemScript.begin()+3 ); + check_spk << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; + return (check_spk == (*this)); + } + + if ( + // these magic numbers correspond to: + // 16_arbitrary_bytes OP_DROP + // OP_IF 32bit_locktime OP_NOP2 OP_DROP pubkey OP_CHECKSIG + // OP_ELSE pubkey OP_CHECKSIG OP_ENDIF + // as provided by artem + redeemScript.size() == 101 && + redeemScript[0] == OP_RETURN && + redeemScript[1] == 0x4c && // PUSH_BYTES + redeemScript[2] == 0x62 && // BYTES + redeemScript[20] == OP_DROP && + redeemScript[21] == OP_IF && + redeemScript[22] == 0x04 && // 32bit locktime + redeemScript[27] == OP_NOP2 && + redeemScript[28] == OP_DROP && + redeemScript[63] == OP_CHECKSIG && + redeemScript[64] == OP_ELSE && + redeemScript[99] == OP_CHECKSIG && + redeemScript[100] == OP_ENDIF + ) { + // Drop the OP_RETURN and OP_PUSHDATA1 + byte + redeemScript.erase(redeemScript.begin(),redeemScript.begin()+3 ); + check_spk << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; + return (check_spk == (*this)); + } + return(false); +} + // this returns true if either there is nothing left and pc points at the end, or // all instructions from the pc to the end of the script are balanced pushes and pops // if there is data, it also returns all the values as byte vectors in a list of vectors diff --git a/src/script/script.h b/src/script/script.h index 1d5af105d0b..00d68e18753 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -598,6 +598,9 @@ class CScript : public CScriptBase bool IsCoinImport() const; bool MayAcceptCryptoCondition() const; + // zHLTC + bool IsRedeemScriptReveal(CScript scriptpubkey) const; + /** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */ bool IsPushOnly(const_iterator pc) const; bool IsPushOnly() const;