From 992fdc3b9ac7fd96e58827e8d8299627ec703021 Mon Sep 17 00:00:00 2001 From: Michael Toutonghi Date: Sun, 15 Apr 2018 23:36:32 -0700 Subject: [PATCH] Tighter locktime encoding + 5 byte support for 2108 issue --- src/komodo_utils.h | 82 +++++++++++++++++++++++++++++++++++----------- src/main.cpp | 5 ++- 2 files changed, 64 insertions(+), 23 deletions(-) diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 792b5f475..e93a04bf6 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -1045,7 +1045,7 @@ int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_ #define SCRIPT_OP_DROP 0x75 // standard spend script -int32_t komodo_standardspend(uint8_t *script,int32_t n,uint8_t rmd160[20]) +int32_t komodo_standardspend(uint8_t *script, int32_t n, uint8_t rmd160[20]) { script[n++] = SCRIPT_OP_DUP; script[n++] = SCRIPT_OP_HASH160; @@ -1057,22 +1057,23 @@ int32_t komodo_standardspend(uint8_t *script,int32_t n,uint8_t rmd160[20]) // check lock time verify script to ensure that the UTXO cannot be spent // until the specified lock time -int32_t komodo_checklocktimeverify(uint8_t *script,int32_t n,uint32_t locktime) +int32_t komodo_checklocktimeverify(uint8_t *script, int32_t n, uint64_t unlocktime) { - script[n++] = 4; - script[n++] = locktime & 0xff, locktime >>= 8; - script[n++] = locktime & 0xff, locktime >>= 8; - script[n++] = locktime & 0xff, locktime >>= 8; - script[n++] = locktime & 0xff; + int numBytes = unlocktime <= 0x7f ? 1 : unlocktime <= 0x7fff ? 2 : unlocktime <= 0x7fffff ? 3 : unlocktime <= 0x7fffffff ? 4 : 5; + script[n++] = numBytes; + + for ( int i = 0; i < numBytes; i++ ) + script[n++] = unlocktime & 0xff, unlocktime >>= 8; + script[n++] = SCRIPT_OP_CHECKLOCKTIMEVERIFY; script[n++] = SCRIPT_OP_DROP; return(n); } // combined CLTV script and standard spend -int32_t komodo_timelockspend(uint8_t *script,int32_t n,uint8_t rmd160[20],uint32_t locktime) +int32_t komodo_timelockspend(uint8_t *script, int32_t n, uint8_t rmd160[20], uint64_t unlocktime) { - n = komodo_checklocktimeverify(script,n,locktime); + n = komodo_checklocktimeverify(script,n,unlocktime); n = komodo_standardspend(script,n,rmd160); return(n); } @@ -1101,28 +1102,69 @@ uint64_t blockPRG(uint32_t nHeight) return(result); } -// create a CLTV output script and return the script and its P2SH address -// funds will be locked a pseudo random time between specified from and to time, with entropy taken from the parameters used -// to setup the chain and the specified block height. this can be used to create, validate, or spend a time locked coin base transaction -// returns locktime -int64_t komodo_block_timelockscript(uint8_t *script, uint8_t p2sh160[20], uint8_t taddrrmd160[20], uint32_t nHeight, uint64_t fromTime, uint64_t toTime) +uint64_t komodo_pr_unlocktime(uint32_t nHeight, uint64_t fromTime, uint64_t toTime) { - uint32_t locktime, i, n = 0; + uint64_t unlocktime; + uint32_t i, n = 0; if ( toTime < fromTime ) return(0); else if ( toTime == fromTime ) - locktime = toTime; + unlocktime = toTime; else { - locktime = blockPRG(nHeight) / (0xffffffffffffffff / ((toTime - fromTime) + 1)); + unlocktime = blockPRG(nHeight) / (0xffffffffffffffff / ((toTime - fromTime) + 1)); // boundary and power of 2 can make it exceed toTime by 1 - locktime = i = (locktime + fromTime) <= toTime ? i : i - 1; + unlocktime = i = (unlocktime + fromTime) <= toTime ? i : i - 1; } - n = komodo_timelockspend(script, n, taddrrmd160, locktime); + return (unlocktime); +} + +// create a CLTV output script and return the script and its P2SH address +// funds will be locked a pseudo random time between specified from and to time, with entropy taken from the parameters used +// to setup the chain and the specified block height. this can be used to create, validate, or spend a time locked coin base transaction +// returns unlocktime +int64_t komodo_block_timelockscript(uint8_t *script, uint8_t *p2sh160, uint8_t taddrrmd160[20], uint32_t nHeight, uint64_t fromTime, uint64_t toTime) +{ + uint32_t n = 0, unlocktime = komodo_pr_unlocktime(nHeight, fromTime, toTime); + + n = komodo_timelockspend(script, n, taddrrmd160, unlocktime); calc_rmd160_sha256(p2sh160, script, n); - return(locktime); + return(unlocktime); +} + +// create an otherwise normal output script to a single address, based on consensus rules, +// including a pseudo random time lock based on block height of this chain and coinbase subsidy +int64_t komodo_coinbase_ouputscript(uint8_t *script, uint8_t *p2sh160, uint8_t taddrrmd160[20], int64_t nSubsidy, uint32_t nHeight) +{ + int n = 0; + + // if it should be locked, lock it, otherwise use standard spend script + if (nSubsidy >= ASSETCHAINS_TIMELOCKGTE) + return komodo_block_timelockscript(script, p2sh160, nHeight, taddrrmd160, ASSETCHAINS_TIMEUNLOCKFROM, ASSETCHAINS_TIMEUNLOCKTO) + else + { + n = komodo_standardspend(script, n, taddrrmd160); + calc_rmd160_sha256(p2sh160, script, n); + return (0); + } +} + +// validate that a time lock script has the correct time lock +int32_t komodo_coinbase_timelockverify(const CTransaction &tx, uint32_t nHeight) +{ + int i; + uint64_t total = 0; + uint64_t timelock = komodo_pr_unlocktime(nHeight, ASSETCHAINS_TIMEUNLOCKFROM, ASSETCHAINS_TIMEUNLOCKTO) + + for (i = 0; total += tx.vout[i].IsNull() ? 0 : tx.vout[i].nValue, i < tx.vout.size(); i++); + + for (int i = 0; i < tx.vout.size(); i++) + { + CScript *script = &(tx.vout[i].scriptPubKey); + // if there should be a timelock, get the time lock from the script and return it + } } long _stripwhite(char *buf,int accept) diff --git a/src/main.cpp b/src/main.cpp index 09d36ee4d..55071a198 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -977,12 +977,11 @@ bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state, { for (i = 0; i < tx.vout.size(); i++) { - // validate that the outputs are locked by the proper time lock script - //uint64_t i = komodo_block_timelockscript(script, scriptHash160, tx.addr/*need address*/) + // validate that the outputs are locked for the proper time + // uint64_t i = komodo_block_timelockscript(script, scriptHash160, tx.addr, nHeight, ASSETCHAINS_TIMEUNLOCKFROM, ASSETCHAINS_TIMEUNLOCKTO) } } } - return true; }