/// <summary> /// /// </summary> /// <param name="transaction">The transaction that the script applies to.</param> /// <param name="script"></param> /// <param name="options"></param> public ScriptEngine(MsgTx transaction, int txIndex, Script script, ScriptOptions options) { if (transaction == null) { throw new ArgumentNullException(nameof(transaction)); } if (txIndex < 0 || txIndex >= transaction.TxIn.Length) { throw new ArgumentOutOfRangeException(nameof(txIndex)); } if (script == null) { throw new ArgumentNullException(nameof(script)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } _transaction = transaction; _txIndex = txIndex; _script = script; _opCodeLookup = new Dictionary <OpCode, Action <ParsedOpCode> >(); Options = options; MainStack = new ScriptStack(Options.AssertScriptIntegerMinimalEncoding); AltStack = new ScriptStack(Options.AssertScriptIntegerMinimalEncoding); BranchStack = new BranchStack(); InitializeOpCodeDictionary(); }
private bool CanExecuteNextOpCode(ParsedOpCode op) { // Ensure that disabled opcodes are always executed. var branchOp = BranchStack.Peek(); return(branchOp == BranchOption.True || op.Code.IsConditional() || op.Code.IsDisabled()); }
private void OpNotIf() { switch (BranchStack.Peek()) { case BranchOption.Skip: case BranchOption.False: BranchStack.Push(BranchOption.Skip); break; case BranchOption.True: BranchStack.Push(!MainStack.PopBool() ? BranchOption.True : BranchOption.False); break; } }
private void OpElse() { switch (BranchStack.Peek()) { case BranchOption.Skip: break; case BranchOption.False: BranchStack.Replace(BranchOption.True); break; case BranchOption.True: BranchStack.Replace(BranchOption.False); break; } }
private void OpEndIf() { BranchStack.Discard(); }