diff --git a/node_modules/bsv/lib/crypto/bn.js b/node_modules/bsv/lib/crypto/bn.js
index 22a5d8f..88d809e 100644
--- a/node_modules/bsv/lib/crypto/bn.js
+++ b/node_modules/bsv/lib/crypto/bn.js
@@ -185,7 +185,8 @@ BN.prototype.toSM = function (opts) {
  * @param {number} size The maximum size.
  */
 BN.fromScriptNumBuffer = function (buf, fRequireMinimal, size) {
-  var nMaxNumSize = size || 4
+  // don't limit numSize default
+  var nMaxNumSize = size || Number.MAX_SAFE_INTEGER;
   $.checkArgument(buf.length <= nMaxNumSize, new Error('script number overflow'))
   if (fRequireMinimal && buf.length > 0) {
     // Check that the number is encoded with the minimum possible
diff --git a/node_modules/bsv/lib/crypto/ecdsa.js b/node_modules/bsv/lib/crypto/ecdsa.js
index 2fa7dfd..2c3f1e5 100644
--- a/node_modules/bsv/lib/crypto/ecdsa.js
+++ b/node_modules/bsv/lib/crypto/ecdsa.js
@@ -9,7 +9,7 @@ var Hash = require('./hash')
 var _ = require('../util/_')
 var $ = require('../util/preconditions')
 
-var ECDSA = function ECDSA (obj) {
+var ECDSA = function ECDSA(obj) {
   if (!(this instanceof ECDSA)) {
     return new ECDSA(obj)
   }
@@ -205,7 +205,7 @@ ECDSA.prototype._findSignature = function (d, e) {
     badrs++
     k = this.k
     Q = G.mul(k)
-    r = Q.x.umod(N)
+    r = new BN(1).mul(Q.x.umod(N))
     s = k.invm(N).mul(e.add(d.mul(r))).umod(N)
   } while (r.cmp(BN.Zero) <= 0 || s.cmp(BN.Zero) <= 0)
 
diff --git a/node_modules/bsv/lib/script/index.js b/node_modules/bsv/lib/script/index.js
index 46683f1..b59a70c 100644
--- a/node_modules/bsv/lib/script/index.js
+++ b/node_modules/bsv/lib/script/index.js
@@ -1,3 +1,5 @@
 module.exports = require('./script')
 
 module.exports.Interpreter = require('./interpreter')
+
+module.exports.Stack = require('./stack')
diff --git a/node_modules/bsv/lib/script/interpreter.js b/node_modules/bsv/lib/script/interpreter.js
index 4185994..0dc40f9 100644
--- a/node_modules/bsv/lib/script/interpreter.js
+++ b/node_modules/bsv/lib/script/interpreter.js
@@ -9,7 +9,7 @@ var Hash = require('../crypto/hash')
 var Signature = require('../crypto/signature')
 var PublicKey = require('../publickey')
 var cloneDeep = require('clone-deep')
-
+var Stack = require('./stack')
 /**
  * Bitcoin transactions contain scripts. Each input has a script called the
  * scriptSig, and each output has a script called the scriptPubkey. To validate
@@ -46,7 +46,7 @@ var Interpreter = function Interpreter (obj) {
  *
  * Translated from bitcoind's VerifyScript
  */
-Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags, satoshisBN) {
+Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags, satoshisBN, sighashScript) {
   var Transaction = require('../transaction')
 
   if (_.isUndefined(tx)) {
@@ -74,7 +74,8 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
     tx: tx,
     nin: nin,
     flags: flags,
-    satoshisBN: satoshisBN
+    satoshisBN: satoshisBN,
+    sighashScript: sighashScript
   })
   var stackCopy
 
@@ -84,12 +85,12 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
   }
 
   // evaluate scriptSig
-  if (!this.evaluate()) {
+  if (!this.evaluate('scriptSig')) {
     return false
   }
 
   if (flags & Interpreter.SCRIPT_VERIFY_P2SH) {
-    stackCopy = this.stack.slice()
+    stackCopy = this.stack.copy()
   }
 
   var stack = this.stack
@@ -100,11 +101,12 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
     tx: tx,
     nin: nin,
     flags: flags,
-    satoshisBN: satoshisBN
+    satoshisBN: satoshisBN,
+    sighashScript: sighashScript
   })
 
   // evaluate scriptPubkey
-  if (!this.evaluate()) {
+  if (!this.evaluate('scriptPubkey')) {
     return false
   }
 
@@ -113,7 +115,7 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
     return false
   }
 
-  var buf = this.stack[this.stack.length - 1]
+  var buf = this.stack.stacktop(-1)
   if (!Interpreter.castToBool(buf)) {
     this.errstr = 'SCRIPT_ERR_EVAL_FALSE_IN_STACK'
     return false
@@ -134,7 +136,7 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
       throw new Error('internal error - stack copy empty')
     }
 
-    var redeemScriptSerialized = stackCopy[stackCopy.length - 1]
+    var redeemScriptSerialized = stackCopy.stacktop(-1)
     var redeemScript = Script.fromBuffer(redeemScriptSerialized)
     stackCopy.pop()
 
@@ -158,7 +160,7 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
       return false
     }
 
-    if (!Interpreter.castToBool(stackCopy[stackCopy.length - 1])) {
+    if (!Interpreter.castToBool(stackCopy.stacktop(-1))) {
       this.errstr = 'SCRIPT_ERR_EVAL_FALSE_IN_P2SH_STACK'
       return false
     }
@@ -172,11 +174,11 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
     // Disallow CLEANSTACK without P2SH, as otherwise a switch
     // CLEANSTACK->P2SH+CLEANSTACK would be possible, which is not a
     // softfork (and P2SH should be one).
-    if ((flags & Interpreter.SCRIPT_VERIFY_P2SH) === 0) {
-      throw new Error('internal error - CLEANSTACK without P2SH')
-    }
+    // if ((flags & Interpreter.SCRIPT_VERIFY_P2SH) === 0) {
+    //   throw new Error('internal error - CLEANSTACK without P2SH')
+    // }
 
-    if (stackCopy.length !== 1) {
+    if (this.stack.length !== 1) {
       this.errstr = 'SCRIPT_ERR_CLEANSTACK'
       return false
     }
@@ -188,14 +190,17 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
 module.exports = Interpreter
 
 Interpreter.prototype.initialize = function (obj) {
-  this.stack = []
-  this.altstack = []
+  this.stack = new Stack([])
+  this.altstack = new Stack([])
   this.pc = 0
   this.pbegincodehash = 0
   this.nOpCount = 0
   this.vfExec = []
   this.errstr = ''
   this.flags = 0
+  // if OP_RETURN is found in executed branches after genesis is activated,
+  // we still have to check if the rest of the script is valid
+  this.nonTopLevelReturnAfterGenesis = false
 }
 
 Interpreter.prototype.set = function (obj) {
@@ -211,10 +216,25 @@ Interpreter.prototype.set = function (obj) {
   this.vfExec = obj.vfExec || this.vfExec
   this.errstr = obj.errstr || this.errstr
   this.flags = typeof obj.flags !== 'undefined' ? obj.flags : this.flags
+  this.sighashScript = obj.sighashScript || this.sighashScript
 }
 
-Interpreter.true = Buffer.from([1])
-Interpreter.false = Buffer.from([])
+Interpreter.prototype.subscript = function () {
+  if (this.sighashScript) {
+    return new Script().set({
+      chunks: this.sighashScript.chunks
+    })
+  } else {
+    // Subset of script starting at the most recent codeseparator
+    // CScript scriptCode(pbegincodehash, pend);
+    return new Script().set({
+      chunks: this.script.chunks.slice(this.pbegincodehash)
+    })
+  }
+}
+
+Interpreter.getTrue = () => Buffer.from([1])
+Interpreter.getFalse = () => Buffer.from([])
 
 Interpreter.MAX_SCRIPT_ELEMENT_SIZE = 520
 Interpreter.MAXIMUM_ELEMENT_SIZE = 4
@@ -329,6 +349,10 @@ Interpreter.SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22)
  */
 Interpreter.SEQUENCE_LOCKTIME_MASK = 0x0000ffff
 
+Interpreter.MAX_SCRIPT_SIZE = Number.MAX_SAFE_INTEGER
+
+Interpreter.MAX_OPCODE_COUNT = Number.MAX_SAFE_INTEGER
+
 Interpreter.castToBool = function (buf) {
   for (var i = 0; i < buf.length; i++) {
     if (buf[i] !== 0) {
@@ -371,13 +395,13 @@ Interpreter.prototype.checkSignatureEncoding = function (buf) {
     }
 
     if (!(this.flags & Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID) &&
-        (sig.nhashtype & Signature.SIGHASH_FORKID)) {
+      (sig.nhashtype & Signature.SIGHASH_FORKID)) {
       this.errstr = 'SCRIPT_ERR_ILLEGAL_FORKID'
       return false
     }
 
     if ((this.flags & Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID) &&
-        !(sig.nhashtype & Signature.SIGHASH_FORKID)) {
+      !(sig.nhashtype & Signature.SIGHASH_FORKID)) {
       this.errstr = 'SCRIPT_ERR_MUST_USE_FORKID'
       return false
     }
@@ -485,21 +509,25 @@ Interpreter._minimallyEncode = function (buf) {
  * Interpreter.prototype.step()
  * bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
  */
-Interpreter.prototype.evaluate = function () {
+Interpreter.prototype.evaluate = function (scriptType) {
   // TODO: script size should be configurable. no magic numbers
-  if (this.script.toBuffer().length > 10000) {
+  if (this.script.toBuffer().length > Interpreter.MAX_SCRIPT_SIZE) {
     this.errstr = 'SCRIPT_ERR_SCRIPT_SIZE'
     return false
   }
 
   try {
     while (this.pc < this.script.chunks.length) {
-      let thisStep = { pc: this.pc, opcode: Opcode.fromNumber(this.script.chunks[this.pc].opcodenum) }
-      var fSuccess = this.step()
+      // fExec: if the opcode will be executed, i.e., not in a false branch
+      let thisStep = { pc: this.pc, fExec: (this.vfExec.indexOf(false) === -1), opcode: Opcode.fromNumber(this.script.chunks[this.pc].opcodenum) }
+
+      var fSuccess = this.step(scriptType)
+
+      this._callbackStep(thisStep)
+
       if (!fSuccess) {
         return false
       }
-      this._callbackStep(thisStep)
     }
 
     // Size limits
@@ -523,13 +551,28 @@ Interpreter.prototype.evaluate = function () {
 Interpreter.prototype._callbackStep = function (thisStep) {
   if (typeof this.stepListener === 'function') {
     try {
-      this.stepListener(thisStep, cloneDeep(this.stack, true), cloneDeep(this.altstack, true))
+      this.stepListener(thisStep, cloneDeep(this.stack.rawstack, true), cloneDeep(this.altstack.rawstack, true), cloneDeep(this.stack.varStack, true))
     } catch (err) {
       console.log(`Error in Step callback:${err}`)
     }
   }
 }
 
+/**
+ * call to update stackvar
+ * @param {*} stack
+ */
+Interpreter.prototype._callbackStack = function (stack, pc, scriptType) {
+  if (typeof this.stackListener === 'function') {
+    try {
+      this.stackListener(stack, pc, scriptType)
+    } catch (err) {
+      var chunk = this.script.chunks[pc]
+      console.error(`Error: ${err} in _updateStack pc: ${pc}, opcode ${Opcode.fromNumber(chunk.opcodenum).toSafeString()}`)
+    }
+  }
+}
+
 /**
  * Checks a locktime parameter with the transaction's locktime.
  * There are two times of nLockTime: lock-by-blockheight and lock-by-blocktime,
@@ -604,7 +647,7 @@ Interpreter.prototype.checkSequence = function (nSequence) {
   // Mask off any bits that do not have consensus-enforced meaning before
   // doing the integer comparisons
   var nLockTimeMask =
-        Interpreter.SEQUENCE_LOCKTIME_TYPE_FLAG | Interpreter.SEQUENCE_LOCKTIME_MASK
+    Interpreter.SEQUENCE_LOCKTIME_TYPE_FLAG | Interpreter.SEQUENCE_LOCKTIME_MASK
   var txToSequenceMasked = new BN(txToSequence & nLockTimeMask)
   var nSequenceMasked = nSequence.and(nLockTimeMask)
 
@@ -618,9 +661,9 @@ Interpreter.prototype.checkSequence = function (nSequence) {
   var SEQUENCE_LOCKTIME_TYPE_FLAG_BN = new BN(Interpreter.SEQUENCE_LOCKTIME_TYPE_FLAG)
 
   if (!((txToSequenceMasked.lt(SEQUENCE_LOCKTIME_TYPE_FLAG_BN) &&
-           nSequenceMasked.lt(SEQUENCE_LOCKTIME_TYPE_FLAG_BN)) ||
-          (txToSequenceMasked.gte(SEQUENCE_LOCKTIME_TYPE_FLAG_BN) &&
-           nSequenceMasked.gte(SEQUENCE_LOCKTIME_TYPE_FLAG_BN)))) {
+    nSequenceMasked.lt(SEQUENCE_LOCKTIME_TYPE_FLAG_BN)) ||
+    (txToSequenceMasked.gte(SEQUENCE_LOCKTIME_TYPE_FLAG_BN) &&
+      nSequenceMasked.gte(SEQUENCE_LOCKTIME_TYPE_FLAG_BN)))) {
     return false
   }
 
@@ -644,11 +687,15 @@ function padBufferToSize (buf, len) {
  * Based on the inner loop of bitcoind's EvalScript function
  * bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
  */
-Interpreter.prototype.step = function () {
+Interpreter.prototype.step = function (scriptType) {
   var self = this
 
   function stacktop (i) {
-    return self.stack[self.stack.length + i]
+    return self.stack.stacktop(i)
+  }
+
+  function vartop (i) {
+    return self.stack.vartop(i)
   }
 
   function isOpcodeDisabled (opcode) {
@@ -692,10 +739,11 @@ Interpreter.prototype.step = function () {
   var fRequireMinimal = (this.flags & Interpreter.SCRIPT_VERIFY_MINIMALDATA) !== 0
 
   // bool fExec = !count(vfExec.begin(), vfExec.end(), false);
-  var fExec = (this.vfExec.indexOf(false) === -1)
+
   var buf, buf1, buf2, spliced, n, x1, x2, bn, bn1, bn2, bufSig, bufPubkey, subscript
   var sig, pubkey
   var fValue, fSuccess
+  var var1, var2, var3
 
   // Read instruction
   var chunk = this.script.chunks[this.pc]
@@ -710,8 +758,11 @@ Interpreter.prototype.step = function () {
     return false
   }
 
+  // Do not execute instructions if Genesis OP_RETURN was found in executed branches.
+  var fExec = (this.vfExec.indexOf(false) === -1) && (!this.nonTopLevelReturnAfterGenesis || opcodenum === Opcode.OP_RETURN)
+
   // Note how Opcode.OP_RESERVED does not count towards the opcode limit.
-  if (opcodenum > Opcode.OP_16 && ++(this.nOpCount) > 201) {
+  if (opcodenum > Opcode.OP_16 && ++(this.nOpCount) > Interpreter.MAX_OPCODE_COUNT) {
     this.errstr = 'SCRIPT_ERR_OP_COUNT'
     return false
   }
@@ -727,7 +778,7 @@ Interpreter.prototype.step = function () {
       return false
     }
     if (!chunk.buf) {
-      this.stack.push(Interpreter.false)
+      this.stack.push(Interpreter.getFalse())
     } else if (chunk.len !== chunk.buf.length) {
       throw new Error(`Length of push value not equal to length of data (${chunk.len},${chunk.buf.length})`)
     } else {
@@ -762,9 +813,9 @@ Interpreter.prototype.step = function () {
         // they push, so no need for a CheckMinimalPush here.
         break
 
-        //
-        // Control
-        //
+      //
+      // Control
+      //
       case Opcode.OP_NOP:
         break
 
@@ -799,7 +850,7 @@ Interpreter.prototype.step = function () {
         // Thus as a special case we tell CScriptNum to accept up
         // to 5-byte bignums, which are good until 2**39-1, well
         // beyond the 2**32-1 limit of the nLockTime field itself.
-        var nLockTime = BN.fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal, 5)
+        var nLockTime = BN.fromScriptNumBuffer(this.stack.stacktop(-1), fRequireMinimal, 5)
 
         // In the rare event that the argument may be < 0 due to
         // some arithmetic being done first, you can always use
@@ -941,19 +992,32 @@ Interpreter.prototype.step = function () {
         break
 
       case Opcode.OP_RETURN:
-        this.errstr = 'SCRIPT_ERR_OP_RETURN'
-        return false
-        // break // unreachable
 
-        //
-        // Stack ops
-        //
+        if ((this.flags & Interpreter.SCRIPT_VERIFY_P2SH) === 0) { // utxo_after_genesis
+          if (this.vfExec.length === 0) {
+            // Terminate the execution as successful. The remaining of the script does not affect the validity (even in
+            // presence of unbalanced IFs, invalid opcodes etc)
+            this.pc = this.script.chunks.length
+            return true
+          }
+          // op_return encountered inside if statement after genesis --> check for invalid grammar
+          this.nonTopLevelReturnAfterGenesis = true
+        } else {
+          return false
+        }
+
+        break
+
+      //
+      // Stack ops
+      //
       case Opcode.OP_TOALTSTACK:
         if (this.stack.length < 1) {
           this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
           return false
         }
-        this.altstack.push(this.stack.pop())
+        var1 = vartop(-1)
+        this.altstack.push(this.stack.pop(), var1)
         break
 
       case Opcode.OP_FROMALTSTACK:
@@ -961,7 +1025,8 @@ Interpreter.prototype.step = function () {
           this.errstr = 'SCRIPT_ERR_INVALID_ALTSTACK_OPERATION'
           return false
         }
-        this.stack.push(this.altstack.pop())
+        const varAlt = this.altstack.vartop(-1)
+        this.stack.push(this.altstack.pop(), varAlt)
         break
 
       case Opcode.OP_2DROP:
@@ -982,8 +1047,10 @@ Interpreter.prototype.step = function () {
         }
         buf1 = stacktop(-2)
         buf2 = stacktop(-1)
-        this.stack.push(Buffer.from(buf1))
-        this.stack.push(Buffer.from(buf2))
+        var1 = vartop(-2)
+        var2 = vartop(-1)
+        this.stack.push(Buffer.from(buf1), `$${var1}`)
+        this.stack.push(Buffer.from(buf2), `$${var2}`)
         break
 
       case Opcode.OP_3DUP:
@@ -995,9 +1062,12 @@ Interpreter.prototype.step = function () {
         buf1 = stacktop(-3)
         buf2 = stacktop(-2)
         var buf3 = stacktop(-1)
-        this.stack.push(Buffer.from(buf1))
-        this.stack.push(Buffer.from(buf2))
-        this.stack.push(Buffer.from(buf3))
+        var1 = vartop(-3)
+        var2 = vartop(-2)
+        var3 = vartop(-1)
+        this.stack.push(Buffer.from(buf1), `$${var1}`)
+        this.stack.push(Buffer.from(buf2), `$${var2}`)
+        this.stack.push(Buffer.from(buf3), `$${var3}`)
         break
 
       case Opcode.OP_2OVER:
@@ -1008,8 +1078,10 @@ Interpreter.prototype.step = function () {
         }
         buf1 = stacktop(-4)
         buf2 = stacktop(-3)
-        this.stack.push(Buffer.from(buf1))
-        this.stack.push(Buffer.from(buf2))
+        var1 = vartop(-4)
+        var2 = vartop(-3)
+        this.stack.push(Buffer.from(buf1), `$${var1}`)
+        this.stack.push(Buffer.from(buf2), `$${var2}`)
         break
 
       case Opcode.OP_2ROT:
@@ -1018,9 +1090,13 @@ Interpreter.prototype.step = function () {
           this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
           return false
         }
+
+        var1 = vartop(-6)
+        var2 = vartop(-5)
+
         spliced = this.stack.splice(this.stack.length - 6, 2)
-        this.stack.push(spliced[0])
-        this.stack.push(spliced[1])
+        this.stack.push(spliced[0], var1)
+        this.stack.push(spliced[1], var2)
         break
 
       case Opcode.OP_2SWAP:
@@ -1029,9 +1105,11 @@ Interpreter.prototype.step = function () {
           this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
           return false
         }
+        var1 = vartop(-4)
+        var2 = vartop(-3)
         spliced = this.stack.splice(this.stack.length - 4, 2)
-        this.stack.push(spliced[0])
-        this.stack.push(spliced[1])
+        this.stack.push(spliced[0], var1)
+        this.stack.push(spliced[1], var2)
         break
 
       case Opcode.OP_IFDUP:
@@ -1043,14 +1121,15 @@ Interpreter.prototype.step = function () {
         buf = stacktop(-1)
         fValue = Interpreter.castToBool(buf)
         if (fValue) {
-          this.stack.push(Buffer.from(buf))
+          var1 = vartop(-1)
+          this.stack.push(Buffer.from(buf), `$${var1}`)
         }
         break
 
       case Opcode.OP_DEPTH:
         // -- stacksize
         buf = new BN(this.stack.length).toScriptNumBuffer()
-        this.stack.push(buf)
+        this.stack.push(buf, '$depth')
         break
 
       case Opcode.OP_DROP:
@@ -1068,7 +1147,8 @@ Interpreter.prototype.step = function () {
           this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
           return false
         }
-        this.stack.push(Buffer.from(stacktop(-1)))
+        var1 = vartop(-1)
+        this.stack.push(Buffer.from(stacktop(-1)), `$${var1}`)
         break
 
       case Opcode.OP_NIP:
@@ -1086,7 +1166,8 @@ Interpreter.prototype.step = function () {
           this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
           return false
         }
-        this.stack.push(Buffer.from(stacktop(-2)))
+        var2 = vartop(-2)
+        this.stack.push(Buffer.from(stacktop(-2)), `$${var2}`)
         break
 
       case Opcode.OP_PICK:
@@ -1098,7 +1179,7 @@ Interpreter.prototype.step = function () {
           return false
         }
         buf = stacktop(-1)
-        bn = BN.fromScriptNumBuffer(buf, fRequireMinimal)
+        bn = BN.fromScriptNumBuffer(buf, fRequireMinimal, 4)
         n = bn.toNumber()
         this.stack.pop()
         if (n < 0 || n >= this.stack.length) {
@@ -1106,10 +1187,14 @@ Interpreter.prototype.step = function () {
           return false
         }
         buf = stacktop(-n - 1)
+        var1 = vartop(-n - 1)
         if (opcodenum === Opcode.OP_ROLL) {
           this.stack.splice(this.stack.length - n - 1, 1)
+          this.stack.push(Buffer.from(buf), var1)
+        } else {
+          this.stack.push(Buffer.from(buf), `$${var1}`)
         }
-        this.stack.push(Buffer.from(buf))
+
         break
 
       case Opcode.OP_ROT:
@@ -1123,9 +1208,13 @@ Interpreter.prototype.step = function () {
         x1 = stacktop(-3)
         x2 = stacktop(-2)
         var x3 = stacktop(-1)
-        this.stack[this.stack.length - 3] = x2
-        this.stack[this.stack.length - 2] = x3
-        this.stack[this.stack.length - 1] = x1
+        var1 = vartop(-3)
+        var2 = vartop(-2)
+        var3 = vartop(-1)
+        this.stack.write(-3, x2)
+        this.stack.write(-2, x3)
+        this.stack.write(-1, x1)
+        this.stack.updateTopVars([var1, var3, var2])
         break
 
       case Opcode.OP_SWAP:
@@ -1136,8 +1225,11 @@ Interpreter.prototype.step = function () {
         }
         x1 = stacktop(-2)
         x2 = stacktop(-1)
-        this.stack[this.stack.length - 2] = x2
-        this.stack[this.stack.length - 1] = x1
+        var1 = vartop(-2)
+        var2 = vartop(-1)
+        this.stack.write(-2, x2)
+        this.stack.write(-1, x1)
+        this.stack.updateTopVars([var1, var2])
         break
 
       case Opcode.OP_TUCK:
@@ -1146,7 +1238,12 @@ Interpreter.prototype.step = function () {
           this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
           return false
         }
+
+        var1 = vartop(-2)
+        var2 = vartop(-1)
+
         this.stack.splice(this.stack.length - 2, 0, Buffer.from(stacktop(-1)))
+        this.stack.updateTopVars([var2, var1, `$${var2}`])
         break
 
       case Opcode.OP_SIZE:
@@ -1156,7 +1253,7 @@ Interpreter.prototype.step = function () {
           return false
         }
         bn = new BN(stacktop(-1).length)
-        this.stack.push(bn.toScriptNumBuffer())
+        this.stack.push(bn.toScriptNumBuffer(), `$size`)
         break
 
       //
@@ -1227,7 +1324,7 @@ Interpreter.prototype.step = function () {
           this.stack.pop()
         } else {
           bn1 = new BN(buf1)
-          bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal)
+          bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, 4)
           n = bn2.toNumber()
           if (n < 0) {
             this.errstr = 'SCRIPT_ERR_INVALID_NUMBER_RANGE'
@@ -1264,7 +1361,7 @@ Interpreter.prototype.step = function () {
         var fEqual = buf1.toString('hex') === buf2.toString('hex')
         this.stack.pop()
         this.stack.pop()
-        this.stack.push(fEqual ? Interpreter.true : Interpreter.false)
+        this.stack.push(fEqual ? Interpreter.getTrue() : Interpreter.getFalse())
         if (opcodenum === Opcode.OP_EQUALVERIFY) {
           if (fEqual) {
             this.stack.pop()
@@ -1275,9 +1372,9 @@ Interpreter.prototype.step = function () {
         }
         break
 
-        //
-        // Numeric
-        //
+      //
+      // Numeric
+      //
       case Opcode.OP_1ADD:
       case Opcode.OP_1SUB:
       case Opcode.OP_NEGATE:
@@ -1312,7 +1409,7 @@ Interpreter.prototype.step = function () {
           case Opcode.OP_0NOTEQUAL:
             bn = new BN((bn.cmp(BN.Zero) !== 0) + 0)
             break
-            // default:      assert(!'invalid opcode'); break; // TODO: does this ever occur?
+          // default:      assert(!'invalid opcode'); break; // TODO: does this ever occur?
         }
         this.stack.pop()
         this.stack.push(bn.toScriptNumBuffer())
@@ -1377,35 +1474,35 @@ Interpreter.prototype.step = function () {
           case Opcode.OP_BOOLAND:
             bn = new BN(((bn1.cmp(BN.Zero) !== 0) && (bn2.cmp(BN.Zero) !== 0)) + 0)
             break
-            // case Opcode.OP_BOOLOR:        bn = (bn1 !== bnZero || bn2 !== bnZero); break;
+          // case Opcode.OP_BOOLOR:        bn = (bn1 !== bnZero || bn2 !== bnZero); break;
           case Opcode.OP_BOOLOR:
             bn = new BN(((bn1.cmp(BN.Zero) !== 0) || (bn2.cmp(BN.Zero) !== 0)) + 0)
             break
-            // case Opcode.OP_NUMEQUAL:      bn = (bn1 === bn2); break;
+          // case Opcode.OP_NUMEQUAL:      bn = (bn1 === bn2); break;
           case Opcode.OP_NUMEQUAL:
             bn = new BN((bn1.cmp(bn2) === 0) + 0)
             break
-            // case Opcode.OP_NUMEQUALVERIFY:    bn = (bn1 === bn2); break;
+          // case Opcode.OP_NUMEQUALVERIFY:    bn = (bn1 === bn2); break;
           case Opcode.OP_NUMEQUALVERIFY:
             bn = new BN((bn1.cmp(bn2) === 0) + 0)
             break
-            // case Opcode.OP_NUMNOTEQUAL:     bn = (bn1 !== bn2); break;
+          // case Opcode.OP_NUMNOTEQUAL:     bn = (bn1 !== bn2); break;
           case Opcode.OP_NUMNOTEQUAL:
             bn = new BN((bn1.cmp(bn2) !== 0) + 0)
             break
-            // case Opcode.OP_LESSTHAN:      bn = (bn1 < bn2); break;
+          // case Opcode.OP_LESSTHAN:      bn = (bn1 < bn2); break;
           case Opcode.OP_LESSTHAN:
             bn = new BN((bn1.cmp(bn2) < 0) + 0)
             break
-            // case Opcode.OP_GREATERTHAN:     bn = (bn1 > bn2); break;
+          // case Opcode.OP_GREATERTHAN:     bn = (bn1 > bn2); break;
           case Opcode.OP_GREATERTHAN:
             bn = new BN((bn1.cmp(bn2) > 0) + 0)
             break
-            // case Opcode.OP_LESSTHANOREQUAL:   bn = (bn1 <= bn2); break;
+          // case Opcode.OP_LESSTHANOREQUAL:   bn = (bn1 <= bn2); break;
           case Opcode.OP_LESSTHANOREQUAL:
             bn = new BN((bn1.cmp(bn2) <= 0) + 0)
             break
-            // case Opcode.OP_GREATERTHANOREQUAL:  bn = (bn1 >= bn2); break;
+          // case Opcode.OP_GREATERTHANOREQUAL:  bn = (bn1 >= bn2); break;
           case Opcode.OP_GREATERTHANOREQUAL:
             bn = new BN((bn1.cmp(bn2) >= 0) + 0)
             break
@@ -1415,7 +1512,7 @@ Interpreter.prototype.step = function () {
           case Opcode.OP_MAX:
             bn = (bn1.cmp(bn2) > 0 ? bn1 : bn2)
             break
-            // default:           assert(!'invalid opcode'); break; //TODO: does this ever occur?
+          // default:           assert(!'invalid opcode'); break; //TODO: does this ever occur?
         }
         this.stack.pop()
         this.stack.pop()
@@ -1446,12 +1543,12 @@ Interpreter.prototype.step = function () {
         this.stack.pop()
         this.stack.pop()
         this.stack.pop()
-        this.stack.push(fValue ? Interpreter.true : Interpreter.false)
+        this.stack.push(fValue ? Interpreter.getTrue() : Interpreter.getFalse())
         break
 
-        //
-        // Crypto
-        //
+      //
+      // Crypto
+      //
       case Opcode.OP_RIPEMD160:
       case Opcode.OP_SHA1:
       case Opcode.OP_SHA256:
@@ -1503,9 +1600,7 @@ Interpreter.prototype.step = function () {
 
         // Subset of script starting at the most recent codeseparator
         // CScript scriptCode(pbegincodehash, pend);
-        subscript = new Script().set({
-          chunks: this.script.chunks.slice(this.pbegincodehash)
-        })
+        subscript = this.subscript()
 
         // Drop the signature, since there's no way for a signature to sign itself
         var tmpScript = new Script().add(bufSig)
@@ -1531,7 +1626,7 @@ Interpreter.prototype.step = function () {
         this.stack.pop()
 
         // stack.push_back(fSuccess ? vchTrue : vchFalse);
-        this.stack.push(fSuccess ? Interpreter.true : Interpreter.false)
+        this.stack.push(fSuccess ? Interpreter.getTrue() : Interpreter.getFalse())
         if (opcodenum === Opcode.OP_CHECKSIGVERIFY) {
           if (fSuccess) {
             this.stack.pop()
@@ -1559,7 +1654,7 @@ Interpreter.prototype.step = function () {
           return false
         }
         this.nOpCount += nKeysCount
-        if (this.nOpCount > 201) {
+        if (this.nOpCount > Interpreter.MAX_OPCODE_COUNT) {
           this.errstr = 'SCRIPT_ERR_OP_COUNT'
           return false
         }
@@ -1592,9 +1687,7 @@ Interpreter.prototype.step = function () {
         }
 
         // Subset of script starting at the most recent codeseparator
-        subscript = new Script().set({
-          chunks: this.script.chunks.slice(this.pbegincodehash)
-        })
+        subscript = this.subscript()
 
         // Drop the signatures, since there's no way for a signature to sign itself
         for (var k = 0; k < nSigsCount; k++) {
@@ -1668,7 +1761,7 @@ Interpreter.prototype.step = function () {
         }
         this.stack.pop()
 
-        this.stack.push(fSuccess ? Interpreter.true : Interpreter.false)
+        this.stack.push(fSuccess ? Interpreter.getTrue() : Interpreter.getFalse())
 
         if (opcodenum === Opcode.OP_CHECKMULTISIGVERIFY) {
           if (fSuccess) {
@@ -1680,9 +1773,9 @@ Interpreter.prototype.step = function () {
         }
         break
 
-        //
-        // Byte string operations
-        //
+      //
+      // Byte string operations
+      //
       case Opcode.OP_CAT:
         if (this.stack.length < 2) {
           this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
@@ -1695,7 +1788,7 @@ Interpreter.prototype.step = function () {
           this.errstr = 'SCRIPT_ERR_PUSH_SIZE'
           return false
         }
-        this.stack[this.stack.length - 2] = Buffer.concat([buf1, buf2])
+        this.stack.write(-2, Buffer.concat([buf1, buf2]))
         this.stack.pop()
         break
 
@@ -1719,13 +1812,13 @@ Interpreter.prototype.step = function () {
         var n1 = Buffer.from(buf1)
 
         // Replace existing stack values by the new values.
-        this.stack[this.stack.length - 2] = n1.slice(0, position)
-        this.stack[this.stack.length - 1] = n1.slice(position)
+        this.stack.write(-2, n1.slice(0, position))
+        this.stack.write(-1, n1.slice(position))
         break
 
-        //
-        // Conversion operations
-        //
+      //
+      // Conversion operations
+      //
       case Opcode.OP_NUM2BIN:
         // (in -- out)
         if (this.stack.length < 2) {
@@ -1755,7 +1848,7 @@ Interpreter.prototype.step = function () {
         // We already have an element of the right size, we
         // don't need to do anything.
         if (rawnum.length === size) {
-          this.stack[this.stack.length - 1] = rawnum
+          this.stack.write(-1, rawnum)
           break
         }
 
@@ -1775,7 +1868,7 @@ Interpreter.prototype.step = function () {
 
         num[l] = signbit
 
-        this.stack[this.stack.length - 1] = num
+        this.stack.write(-1, num)
         break
 
       case Opcode.OP_BIN2NUM:
@@ -1788,7 +1881,7 @@ Interpreter.prototype.step = function () {
         buf1 = stacktop(-1)
         buf2 = Interpreter._minimallyEncode(buf1)
 
-        this.stack[this.stack.length - 1] = buf2
+        this.stack.write(-1, buf2)
 
         // The resulting number must be a valid number.
         if (!Interpreter._isMinimallyEncoded(buf2)) {
@@ -1803,5 +1896,10 @@ Interpreter.prototype.step = function () {
     }
   }
 
+  // only when next opcode is evaluate opcode, we update stack
+  if (this.vfExec.indexOf(false) === -1) {
+    this._callbackStack(this.stack, this.pc, scriptType)
+  }
+
   return true
 }
diff --git a/node_modules/bsv/lib/script/stack.js b/node_modules/bsv/lib/script/stack.js
new file mode 100644
index 0000000..a439096
--- /dev/null
+++ b/node_modules/bsv/lib/script/stack.js
@@ -0,0 +1,92 @@
+'use strict'
+
+var Stack = function Stack (rawstack, varStack) {
+  this.stack = rawstack
+  this.varStack = varStack || []
+}
+
+module.exports = Stack
+
+Stack.prototype.pushVar = function (varName) {
+  this.varStack.push(varName || '$tmp')
+}
+
+Stack.prototype.popVar = function () {
+  this.varStack.pop()
+}
+
+Stack.prototype.push = function (n, varName) {
+  this.pushVar(varName)
+  this.stack.push(n)
+  this.checkConsistency()
+}
+
+Stack.prototype.pop = function () {
+  this.popVar()
+  let top = this.stack.pop()
+  this.checkConsistency()
+  return top
+}
+
+Stack.prototype.updateTopVars = function (vars) {
+  if (vars.length > this.varStack.length) {
+    throw new Error(`updateTopVars fail, stack: ${this.stack.length},  varStack: ${this.varStack.length}, vars:${vars.length}`)
+  }
+  vars = vars.reverse()
+  this.varStack.splice(this.varStack.length - vars.length, vars.length, ...vars)
+}
+
+Stack.prototype.stacktop = function (i) {
+  return this.stack[this.stack.length + i]
+}
+
+Stack.prototype.vartop = function (i) {
+  return this.varStack[this.varStack.length + i]
+}
+
+Stack.prototype.slice = function (start, end) {
+  return this.stack.slice(start, end)
+}
+
+Stack.prototype.splice = function (start, deleteCount, ...items) {
+  this.varStack.splice(start, deleteCount, ...items)
+  return this.stack.splice(start, deleteCount, ...items)
+}
+
+Stack.prototype.write = function (i, value) {
+  this.stack[this.stack.length + i] = value
+}
+
+Stack.prototype.copy = function () {
+  return new Stack(this.stack.slice() || [], this.varStack.slice() || [])
+}
+
+Stack.prototype.printVarStack = function () {
+  console.log(this.varStack.join(','))
+}
+
+Stack.prototype.checkConsistency = function () {
+  if (this.stack.length !== this.varStack.length) {
+    this.printVarStack()
+    throw new Error(`checkConsistency fail, stack: ${this.stack.length}, varStack:${this.varStack.length}`)
+  }
+}
+
+Stack.prototype.checkConsistencyWithVars = function (varStack) {
+  if (this.stack.length < varStack.length) {
+    this.printVarStack()
+    throw new Error(`checkConsistencyWithVars fail, stack: ${this.stack.length}, varStack:${varStack.length}`)
+  }
+}
+
+Object.defineProperty(Stack.prototype, 'length', {
+  get: function () {
+    return this.stack.length
+  }
+})
+
+Object.defineProperty(Stack.prototype, 'rawstack', {
+  get: function () {
+    return this.stack
+  }
+})
diff --git a/node_modules/bsv/lib/transaction/input/input.js b/node_modules/bsv/lib/transaction/input/input.js
index 98df9b0..494efbb 100644
--- a/node_modules/bsv/lib/transaction/input/input.js
+++ b/node_modules/bsv/lib/transaction/input/input.js
@@ -15,7 +15,7 @@ var DEFAULT_RBF_SEQNUMBER = MAXINT - 2
 var DEFAULT_SEQNUMBER = MAXINT
 var DEFAULT_LOCKTIME_SEQNUMBER = MAXINT - 1
 
-function Input (params) {
+function Input(params) {
   if (!(this instanceof Input)) {
     return new Input(params)
   }
@@ -72,7 +72,7 @@ Input.prototype._fromObject = function (params) {
   return this
 }
 
-Input.prototype.toObject = Input.prototype.toJSON = function toObject () {
+Input.prototype.toObject = Input.prototype.toJSON = function toObject() {
   var obj = {
     prevTxId: this.prevTxId.toString('hex'),
     outputIndex: this.outputIndex,
@@ -167,11 +167,11 @@ Input.prototype.isFinal = function () {
 }
 
 Input.prototype.addSignature = function () {
-  throw new errors.AbstractMethodInvoked('Input#addSignature')
+  // throw new errors.AbstractMethodInvoked('Input#addSignature')
 }
 
 Input.prototype.clearSignatures = function () {
-  throw new errors.AbstractMethodInvoked('Input#clearSignatures')
+  // throw new errors.AbstractMethodInvoked('Input#clearSignatures')
 }
 
 Input.prototype.isValidSignature = function (transaction, signature) {
