mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-24 23:08:31 +01:00
implement toInt function for all signed/unsigned numbers, add Int64 boolean operators to ScriptNumber
This commit is contained in:
parent
de999ab03b
commit
6d4763acf4
7 changed files with 38 additions and 25 deletions
|
@ -31,7 +31,7 @@ trait TransactionSignatureComponent {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
def scriptSignature = transaction.inputs(inputIndex.underlying.toInt).scriptSignature
|
||||
def scriptSignature = transaction.inputs(inputIndex.toInt).scriptSignature
|
||||
/**
|
||||
* The scriptPubKey for which the input is being checked against
|
||||
*
|
||||
|
|
|
@ -64,7 +64,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper with Bit
|
|||
|
||||
logger.info("After Bitcoin-S Script to be connected: " + scriptWithOpCodeSeparatorsRemoved)
|
||||
|
||||
val inputToSign = inputSigsRemoved(inputIndex.underlying.toInt)
|
||||
val inputToSign = inputSigsRemoved(inputIndex.toInt)
|
||||
|
||||
// Set the input to the script of its output. Bitcoin Core does this but the step has no obvious purpose as
|
||||
// the signature covers the hash of the prevout transaction which obviously includes the output script
|
||||
|
|
|
@ -18,20 +18,20 @@ trait TransactionConstants {
|
|||
*
|
||||
* @return the mask that ben used with a bitwise and to indicate if the sequence number has any meaning
|
||||
*/
|
||||
def locktimeDisabledFlag = 1L << 31
|
||||
def locktimeDisabledFlag = UInt32(1L << 31)
|
||||
|
||||
/**
|
||||
* If a transaction's input's sequence number encodes a relative lock-time, this mask is
|
||||
* applied to extract that lock-time from the sequence field.
|
||||
*/
|
||||
def sequenceLockTimeMask = 0x0000ffff
|
||||
def sequenceLockTimeMask = UInt32(0x0000ffff)
|
||||
|
||||
/**
|
||||
* If the transaction input sequence number encodes a relative lock-time and this flag
|
||||
* is set, the relative lock-time has units of 512 seconds,
|
||||
* otherwise it specifies blocks with a granularity of 1.
|
||||
*/
|
||||
def sequenceLockTimeTypeFlag = 1L << 22
|
||||
def sequenceLockTimeTypeFlag = UInt32(1L << 22)
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -341,7 +341,7 @@ object ScriptProgram {
|
|||
*/
|
||||
def factory(transaction: Transaction, scriptPubKey : ScriptPubKey, inputIndex : UInt32,
|
||||
flags : Seq[ScriptFlag]) : PreExecutionScriptProgram = {
|
||||
val script = transaction.inputs(inputIndex.underlying.toInt).scriptSignature.asm
|
||||
val script = transaction.inputs(inputIndex.toInt).scriptSignature.asm
|
||||
apply(transaction,scriptPubKey,inputIndex,script.toList,flags)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.bitcoins.core.script.constant
|
||||
|
||||
import org.bitcoins.core.number.Int64
|
||||
import org.bitcoins.core.script.ScriptOperationFactory
|
||||
import org.bitcoins.core.util.{BitcoinSUtil, BitcoinScriptUtil, Factory}
|
||||
|
||||
|
@ -23,7 +24,8 @@ sealed trait ScriptToken {
|
|||
|
||||
/**
|
||||
* The byte representation of this script token
|
||||
* @return
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def bytes : Seq[Byte] = BitcoinSUtil.decodeHex(hex)
|
||||
|
||||
|
@ -50,7 +52,8 @@ trait ScriptOperation extends ScriptToken {
|
|||
sealed trait ScriptConstant extends ScriptToken {
|
||||
/**
|
||||
* Returns if the constant is encoded in the shortest possible way
|
||||
* @return
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def isShortestEncoding : Boolean = BitcoinScriptUtil.isShortestEncoding(this)
|
||||
}
|
||||
|
@ -62,7 +65,8 @@ sealed trait ScriptConstant extends ScriptToken {
|
|||
sealed trait ScriptNumber extends ScriptConstant {
|
||||
/**
|
||||
* The underlying number of the ScriptNumber
|
||||
* @return
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def underlying : Long
|
||||
|
||||
|
@ -77,7 +81,14 @@ sealed trait ScriptNumber extends ScriptConstant {
|
|||
def > (that : ScriptNumber) : Boolean = underlying > that.underlying
|
||||
def >= (that : ScriptNumber) : Boolean = underlying >= that.underlying
|
||||
|
||||
def &(that : ScriptNumber) : ScriptNumber = ScriptNumber(underlying & that.underlying)
|
||||
def < (that : Int64) : Boolean = underlying < that.underlying
|
||||
def <= (that : Int64) : Boolean = underlying <= that.underlying
|
||||
def > (that : Int64) : Boolean = underlying > that.underlying
|
||||
def >= (that : Int64) : Boolean = underlying >= that.underlying
|
||||
|
||||
|
||||
def & (that : ScriptNumber) : ScriptNumber = ScriptNumber(underlying & that.underlying)
|
||||
def & (that : Int64) : ScriptNumber = ScriptNumber(underlying & that.underlying)
|
||||
|
||||
def | (that : ScriptNumber) : ScriptNumber = ScriptNumber(underlying | that.underlying)
|
||||
|
||||
|
@ -85,7 +96,8 @@ sealed trait ScriptNumber extends ScriptConstant {
|
|||
* This equality just checks that the underlying scala numbers are equivalent, NOT if the numbers
|
||||
* are bitwise equivalent in Script. For instance ScriptNumber(0x01).numEqual(ScriptNumber(0x00000000001)) == true
|
||||
* but (ScriptNumber(0x01) == (ScriptNumber(0x00000000001))) == false
|
||||
* @param that
|
||||
*
|
||||
* @param that
|
||||
* @return
|
||||
*/
|
||||
def numEqual(that : ScriptNumber) : Boolean = underlying == that.underlying
|
||||
|
@ -191,6 +203,7 @@ case object OP_PUSHDATA2 extends ScriptOperation {
|
|||
|
||||
/**
|
||||
* The max amount of data that OP_PUSHDATA2 can push onto the stack
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def max = 65535
|
||||
|
@ -204,6 +217,7 @@ case object OP_PUSHDATA4 extends ScriptOperation {
|
|||
|
||||
/**
|
||||
* The maximum amount of data that OP_PUSHDATA4 can be push on the stack
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def max = 4294967295L
|
||||
|
|
|
@ -131,7 +131,7 @@ trait LockTimeInterpreter extends BitcoinSLogger {
|
|||
* @return if the given script number is valid or not
|
||||
*/
|
||||
def checkSequence(program : ScriptProgram, nSequence : ScriptNumber) : Boolean = {
|
||||
val inputIndex = program.txSignatureComponent.inputIndex.underlying.toInt
|
||||
val inputIndex = program.txSignatureComponent.inputIndex.toInt
|
||||
logger.debug("inputIndex: " + inputIndex)
|
||||
val transaction = program.txSignatureComponent.transaction
|
||||
val txToSequence : Int64 = Int64(transaction.inputs(inputIndex).sequence.underlying)
|
||||
|
@ -141,10 +141,9 @@ trait LockTimeInterpreter extends BitcoinSLogger {
|
|||
return false
|
||||
}
|
||||
|
||||
val nLockTimeMask : UInt32 = UInt32(TransactionConstants.sequenceLockTimeTypeFlag | TransactionConstants.sequenceLockTimeMask)
|
||||
val txToSequenceMasked : Int64 = Int64(txToSequence.underlying & Int64(nLockTimeMask.underlying).underlying)
|
||||
|
||||
val nSequenceMasked : ScriptNumber = nSequence & ScriptNumber(nLockTimeMask.underlying)
|
||||
val nLockTimeMask : UInt32 = UInt32(TransactionConstants.sequenceLockTimeTypeFlag.underlying | TransactionConstants.sequenceLockTimeMask.underlying)
|
||||
val txToSequenceMasked : Int64 = Int64(txToSequence.underlying & nLockTimeMask.underlying)
|
||||
val nSequenceMasked : ScriptNumber = nSequence & Int64(nLockTimeMask.underlying)
|
||||
|
||||
logger.info("tx sequence number: " + transaction.inputs(inputIndex).sequence)
|
||||
logger.info("txToSequenceMasked: " + txToSequenceMasked)
|
||||
|
@ -159,10 +158,10 @@ trait LockTimeInterpreter extends BitcoinSLogger {
|
|||
// unless the type of nSequenceMasked being tested is the same as
|
||||
// the nSequenceMasked in the transaction.
|
||||
if (!(
|
||||
(txToSequenceMasked.underlying < TransactionConstants.sequenceLockTimeTypeFlag &&
|
||||
nSequenceMasked.underlying < TransactionConstants.sequenceLockTimeTypeFlag) ||
|
||||
(txToSequenceMasked.underlying >= TransactionConstants.sequenceLockTimeTypeFlag &&
|
||||
nSequenceMasked.underlying >= TransactionConstants.sequenceLockTimeTypeFlag)
|
||||
(txToSequenceMasked < Int64(TransactionConstants.sequenceLockTimeTypeFlag.underlying) &&
|
||||
nSequenceMasked < Int64(TransactionConstants.sequenceLockTimeTypeFlag.underlying)) ||
|
||||
(txToSequenceMasked >= Int64(TransactionConstants.sequenceLockTimeTypeFlag.underlying) &&
|
||||
nSequenceMasked >= Int64(TransactionConstants.sequenceLockTimeTypeFlag.underlying))
|
||||
)) {
|
||||
logger.error("The nSequence mask is not the same as it was in the transaction")
|
||||
return false
|
||||
|
@ -170,7 +169,7 @@ trait LockTimeInterpreter extends BitcoinSLogger {
|
|||
|
||||
// Now that we know we're comparing apples-to-apples, the
|
||||
// comparison is a simple numeric one.
|
||||
if (nSequenceMasked.underlying > txToSequenceMasked.underlying) {
|
||||
if (nSequenceMasked > Int64(txToSequenceMasked.underlying)) {
|
||||
logger.error("OP_CSV fails because locktime in transaction has not been met yet")
|
||||
return false
|
||||
}
|
||||
|
@ -195,7 +194,7 @@ trait LockTimeInterpreter extends BitcoinSLogger {
|
|||
// unless the type of nLockTime being tested is the same as
|
||||
// the nLockTime in the transaction.
|
||||
val transaction = program.txSignatureComponent.transaction
|
||||
val input = transaction.inputs(program.txSignatureComponent.inputIndex.underlying.toInt)
|
||||
val input = transaction.inputs(program.txSignatureComponent.inputIndex.toInt)
|
||||
if (!(
|
||||
(transaction.lockTime < TransactionConstants.locktimeThreshold && UInt32(locktime.underlying) < TransactionConstants.locktimeThreshold) ||
|
||||
(transaction.lockTime >= TransactionConstants.locktimeThreshold && UInt32(locktime.underlying) >= TransactionConstants.locktimeThreshold)
|
||||
|
@ -203,7 +202,7 @@ trait LockTimeInterpreter extends BitcoinSLogger {
|
|||
|
||||
// Now that we know we're comparing apples-to-apples, the
|
||||
// comparison is a simple numeric one.
|
||||
if (locktime.underlying > Int64(transaction.lockTime.underlying).underlying) return false
|
||||
if (locktime > Int64(transaction.lockTime.underlying)) return false
|
||||
|
||||
// Finally the nLockTime feature can be disabled and thus
|
||||
// CHECKLOCKTIMEVERIFY bypassed if every txin has been
|
||||
|
@ -226,5 +225,5 @@ trait LockTimeInterpreter extends BitcoinSLogger {
|
|||
* @param s
|
||||
* @return
|
||||
*/
|
||||
def isLockTimeBitOff(s : ScriptNumber) : Boolean = (s.underlying & TransactionConstants.locktimeDisabledFlag) == 0
|
||||
def isLockTimeBitOff(s : ScriptNumber) : Boolean = (s.underlying & TransactionConstants.locktimeDisabledFlag.underlying) == 0
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ class LockTimeInterpreterTest extends FlatSpec with MustMatchers with LockTimeIn
|
|||
}
|
||||
|
||||
it must "treat OP_CHECKSEQUENCEVERIFY as a NOP if the locktime disabled flag is set in the sequence number" in {
|
||||
val stack = List(ScriptNumber(TransactionConstants.locktimeDisabledFlag))
|
||||
val stack = List(ScriptNumber(TransactionConstants.locktimeDisabledFlag.underlying))
|
||||
val script = List(OP_CHECKSEQUENCEVERIFY)
|
||||
val program = ScriptProgram(TestUtil.testProgramExecutionInProgress,stack,script)
|
||||
val newProgram = opCheckSequenceVerify(program)
|
||||
|
|
Loading…
Add table
Reference in a new issue