private void OpLeft(ParsedOpCode op) { var high = MainStack.PopInt32(); var data = MainStack.Pop(); if (data.Length == 0 || high == 0) { MainStack.Push(new byte[0]); } else if (high < 0) { throw new ScriptIndexOutOfRangeException(op.Code, "upper boundary less than zero"); } else if (high > data.Length) { throw new ScriptIndexOutOfRangeException(op.Code, "upper boundary greater than array length"); } else if (high < 0) { throw new ScriptIndexOutOfRangeException(op.Code, "upper boundary less than zero"); } else { var bytes = data.Take(high).ToArray(); MainStack.Push(bytes); } }
private void OpSubStr(ParsedOpCode op) { var startIndex = MainStack.PopInt32(); var endIndexExclusive = MainStack.PopInt32(); var array = MainStack.Pop(); if (array.Length == 0) { MainStack.Push(new byte[0]); } else if (startIndex < 0 || endIndexExclusive < 0) { throw new ScriptIndexOutOfRangeException(op.Code, "Negative substring index"); } else if (startIndex > array.Length || endIndexExclusive > array.Length) { throw new ScriptIndexOutOfRangeException(op.Code, "Substring index out of bounds"); } else if (startIndex > endIndexExclusive) { throw new ScriptIndexOutOfRangeException(op.Code, "Start index is greater than end index"); } else if (startIndex == endIndexExclusive) { MainStack.Push(new byte[0]); } else { var substr = array.Skip(startIndex).Take(endIndexExclusive - startIndex).ToArray(); MainStack.Push(substr); } }
private void OpNumNotEqual(ParsedOpCode obj) { var a = MainStack.PopInt32(); var b = MainStack.PopInt32(); MainStack.Push(a != b ? 1 : 0); }
private void OpNop(ParsedOpCode op) { if (Options.DiscourageUpgradableNops) { throw new ReservedOpCodeException(op.Code); } }
private void OpEqual(ParsedOpCode op) { var a = MainStack.Pop(); var b = MainStack.Pop(); MainStack.Push(a.SequenceEqual(b)); }
private void OpXor(ParsedOpCode op) { var a = MainStack.PopInt32(); var b = MainStack.PopInt32(); MainStack.Push(a ^ b); }
private void OpNumEqual(ParsedOpCode op) { var a = MainStack.PopInt32(); var b = MainStack.PopInt32(); MainStack.Push(a == b ? 1 : 0); }
public void OpCheckSig(ParsedOpCode op, MsgTx transaction) { try { var rawPublicKey = MainStack.Pop(); var rawSignature = MainStack.Pop(); if (rawSignature.Length < 1) { MainStack.Push(false); return; } var signature = rawSignature.Take(rawSignature.Length - 1).ToArray(); var signatureType = (SignatureHashType)rawSignature.Last(); AssertSignatureHashType(signatureType); AssertSignatureEncoding(signature); AssertPublicKeyEncoding(rawPublicKey); var subScript = _script.GetOpCodesWithoutData(rawSignature); var hash = CalculateSignatureHash(subScript, signatureType, (MsgTx)transaction.Clone(), _txIndex); var ecSignature = new ECSignature(signature); var securityService = new ECPublicSecurityService(rawPublicKey); var isValidSignature = securityService.VerifySignature(hash, ecSignature); MainStack.Push(isValidSignature); } catch (ScriptException) { MainStack.Push(false); } }
/// <summary> /// Multiplies top two numbers on the stack. /// </summary> /// <param name="obj"></param> private void OpMul(ParsedOpCode obj) { var a = MainStack.PopInt32(); var b = MainStack.PopInt32(); MainStack.Push(a * b); }
private void OpLessThan(ParsedOpCode obj) { var a = MainStack.PopInt32(); var b = MainStack.PopInt32(); MainStack.Push(b < a ? 1 : 0); }
private void OpGreaterThanOrEqual(ParsedOpCode obj) { var a = MainStack.PopInt32(); var b = MainStack.PopInt32(); MainStack.Push(b > a ? 1 : 0); }
private void Execute(ParsedOpCode op) { if (!_opCodeLookup.TryGetValue(op.Code, out var action)) { throw new ScriptSyntaxErrorException(($"Attempted to execute unknown op code 0x{(byte) op.Code:X}")); } if (op.Code.IsReserved()) { throw new ReservedOpCodeException(op.Code); } try { action(op); } catch (ScriptException) { throw; } catch (Exception ex) { throw new Exception( "Unexpected error while running script. " + $"OpCode: {op.Code} " + $"Data: '{Hex.ToHexString(op.Data)}'", ex); } }
private void OpHash160(ParsedOpCode obj) { var value = MainStack.Pop(); var hash = HashUtil.Ripemd160(HashUtil.Blake256(value)); MainStack.Push(hash); }
public void AddData(byte[] data) { var opCode = OpCodeUtil.CanonicalOpCodeForData(data); var parsedOpCode = new ParsedOpCode(opCode, data); AddOpCode(parsedOpCode); }
private void OpMax(ParsedOpCode obj) { var a = MainStack.PopInt32(); var b = MainStack.PopInt32(); MainStack.Push(Math.Max(a, b)); }
private void OpSub(ParsedOpCode obj) { var a = MainStack.PopInt32(); var b = MainStack.PopInt32(); MainStack.Push(b - a); }
private void OpBoolOr(ParsedOpCode obj) { var a = MainStack.PopInt32(); var b = MainStack.PopInt32(); MainStack.Push(a != 0 || b != 0 ? 1 : 0); }
private void OpWithin(ParsedOpCode obj) { var max = MainStack.PopInt32(); var min = MainStack.PopInt32(); var test = MainStack.PopInt32(); MainStack.Push(min <= test && test < max ? 1 : 0); }
private void OpCat(ParsedOpCode op) { var first = MainStack.Pop(); var second = MainStack.Pop(); var bytes = second.Concat(first).ToArray(); MainStack.Push(bytes); }
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 OpPushData(ParsedOpCode op) { if (op.Code.IsOpN()) { var value = (op.Code - OpCode.OP_1) + 1; MainStack.Push(value); } else { MainStack.Push(op.Data); } }
private void OpMod(ParsedOpCode op) { var a = MainStack.PopInt32(); var b = MainStack.PopInt32(); if (a == 0) { throw new ArithemeticException(op.Code, "Division by zero"); } MainStack.Push(b % a); }
private void OpSha256(ParsedOpCode op) { if (!Options.EnableSha256) { OpNop(op); return; } var data = MainStack.Pop(); var hash = HashUtil.Sha256(data); MainStack.Push(hash); }
private void OpRShift(ParsedOpCode op) { var a = MainStack.PopInt32(); var b = MainStack.PopInt32(); if (a < 0) { throw new ScriptIndexOutOfRangeException(op.Code, "Negative shift"); } if (a > 32) { throw new ScriptIndexOutOfRangeException(op.Code, "Shift overflow"); } MainStack.Push(b >> a); }
private void OpRotl(ParsedOpCode op) { var rotate = MainStack.PopInt32(); var value = MainStack.PopInt32(); if (rotate < 0) { throw new ScriptIndexOutOfRangeException(op.Code, "attempted to rotate by negative value"); } if (rotate > 31) { throw new ScriptIndexOutOfRangeException(op.Code, "attempted to rotate by value > 31"); } var rotatedValue = (value << rotate) | (value >> (32 - rotate)); MainStack.Push(rotatedValue); }
private void OpRight(ParsedOpCode op) { var index = MainStack.PopInt32(); var data = MainStack.Pop(); if (data.Length == 0 || index == data.Length) { MainStack.Push(new byte[0]); } else if (index < 0) { throw new ScriptIndexOutOfRangeException(op.Code, "upper boundary less than zero"); } else if (index > data.Length) { throw new ScriptIndexOutOfRangeException(op.Code, "upper boundary greater than array length"); } else { MainStack.Push(data.Skip(index).ToArray()); } }
public void AddOpCode(ParsedOpCode opCode) { _scriptBytes.AddRange(opCode.Serialize()); }
private void OpInvalid(ParsedOpCode op) { throw new InvalidOpCodeException(op.Code); }
private void OpHash256(ParsedOpCode obj) { var value = MainStack.Pop(); MainStack.Push(HashUtil.Blake256D(value)); }
private void OpCheckSigVerify(ParsedOpCode op, MsgTx transaction) { OpCheckSig(op, transaction); OpVerify(); }