static string StackItemToString(StackItem item, string?typeHint = null) { return(typeHint switch { "Boolean" => item.GetBoolean().ToString(), "Integer" => item.GetBigInteger().ToString(), "String" => item.GetString(), _ => item.GetBigInteger().ToHexString(), });
public void TestTotalSupply() { var mockSnapshot = new Mock <Snapshot>(); var myDataCache = new TestDataCache <StorageKey, StorageItem>(); StorageItem item = new StorageItem { Value = new byte[] { 0x01 } }; var key = CreateStorageKey(Prefix_TotalSupply); var ServiceHash = "test".ToInteropMethodHash(); byte[] script = null; using (ScriptBuilder sb = new ScriptBuilder()) { sb.EmitSysCall(ServiceHash); script = sb.ToArray(); } var Hash = script.ToScriptHash(); key.ScriptHash = Hash; myDataCache.Add(key, item); mockSnapshot.SetupGet(p => p.Storages).Returns(myDataCache); TestNep5Token test = new TestNep5Token(); ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, mockSnapshot.Object, 0); StackItem stackItem = test.TotalSupply(ae, null); stackItem.GetBigInteger().Should().Be(1); }
static JToken StackItemToJson(StackItem item, string?typeHint) { return(typeHint switch { "Boolean" => item.GetBoolean().ToString(), "Integer" => item.GetBigInteger().ToString(), "String" => item.GetString(), _ => item switch { Neo.VM.Types.Boolean _ => item.GetBoolean().ToString(), Neo.VM.Types.ByteArray _ => $"{item.GetBigInteger().ToHexString()} ({item.GetString()})", Neo.VM.Types.Integer _ => item.GetBigInteger().ToString(), Neo.VM.Types.Array array => new JArray(array.Select(i => StackItemToJson(i, null))), _ => throw new NotSupportedException(item.GetType().Name), } });
public void TestTotalSupplyDecimal() { var snapshot = Blockchain.Singleton.GetSnapshot(); TestNep5Token test = new TestNep5Token(); BigInteger totalSupply = 100_000_000; totalSupply *= test.Factor; StorageItem item = new StorageItem { Value = totalSupply.ToByteArrayStandard() }; var key = CreateStorageKey(Prefix_TotalSupply); var ServiceHash = "test".ToInteropMethodHash(); byte[] script = null; using (ScriptBuilder sb = new ScriptBuilder()) { sb.EmitSysCall(ServiceHash); script = sb.ToArray(); } var Hash = script.ToScriptHash(); key.ScriptHash = Hash; snapshot.Storages.Add(key, item); ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, snapshot, 0); StackItem stackItem = test.TotalSupply(ae, null); stackItem.GetBigInteger().Should().Be(10_000_000_000_000_000); }
public static string StackItemAsString(StackItem item, bool addQuotes = false) { if (item.IsArray) { var s = new StringBuilder(); var items = item.GetArray(); s.Append('['); for (int i = 0; i < items.Length; i++) { var element = items[i]; if (i > 0) { s.Append(','); } s.Append(StackItemAsString(element)); } s.Append(']'); return(s.ToString()); } if (item is Neo.VM.Types.Boolean) { return(item.GetBoolean().ToString()); } if (item is Neo.VM.Types.Integer) { return(item.GetBigInteger().ToString()); } if (item is Neo.VM.Types.InteropInterface) { return("{InteropInterface}"); } var data = item.GetByteArray(); if (data == null) { return("[Null]"); } if (data == null || data.Length == 0) { return("False"); } return(FormattingUtils.OutputData(data, addQuotes)); }
private void DumpItem(StackItem item, int space = 0) { var spacestr = ""; for (var i = 0; i < space; i++) { spacestr += " "; } Console.WriteLine(spacestr + "got Param:" + item.GetType().ToString()); if (item is Neo.VM.Types.Array || item is Neo.VM.Types.Struct) { var array = item as Neo.VM.Types.Array; for (var i = 0; i < array.Count; i++) { var subitem = array[i]; DumpItem(subitem, space + 1); } } else if (item is Neo.VM.Types.Map) { var map = item as Neo.VM.Types.Map; foreach (var subitem in map) { Console.WriteLine("---Key---"); DumpItemShort(subitem.Key, space + 1); Console.WriteLine("---Value---"); DumpItem(subitem.Value, space + 1); } } else { Console.WriteLine(spacestr + "--as num:" + item.GetBigInteger()); Console.WriteLine(spacestr + "--as bin:" + NeonTestTool.Bytes2HexString(item.GetByteArray())); if (item is Neo.VM.Types.ByteArray) { var str = item.GetString(); if (CheckAsciiChar(str)) { Console.WriteLine(spacestr + "--as str:" + item.GetString()); } } } }
public void TestTotalSupply() { var snapshot = Blockchain.Singleton.GetSnapshot(); StorageItem item = new StorageItem { Value = new byte[] { 0x01 } }; var key = CreateStorageKey(Prefix_TotalSupply); key.Id = test.Id; snapshot.Storages.Add(key, item); ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, snapshot, 0); StackItem stackItem = test.TotalSupply(ae, null); stackItem.GetBigInteger().Should().Be(1); }
public static ContractParameter ToParameter(this StackItem item) { switch (item.GetType().Name) { case "Array": case "Struct": return(new ContractParameter { Type = ContractParameterType.Array, Value = item.GetArray().Select(p => p.ToParameter()).ToArray() }); case "Boolean": return(new ContractParameter { Type = ContractParameterType.Boolean, Value = item.GetBoolean() }); case "ByteArray": return(new ContractParameter { Type = ContractParameterType.ByteArray, Value = item.GetByteArray() }); case "Integer": return(new ContractParameter { Type = ContractParameterType.Integer, Value = item.GetBigInteger() }); case "InteropInterface": return(new ContractParameter { Type = ContractParameterType.InteropInterface }); default: throw new ArgumentException(); } }
public static ContractParameter ToParameter(this StackItem item) { switch (item) { case VMArray array: return(new ContractParameter { Type = ContractParameterType.Array, Value = array.Select(p => p.ToParameter()).ToArray() }); case VMBoolean _: return(new ContractParameter { Type = ContractParameterType.Boolean, Value = item.GetBoolean() }); case ByteArray _: return(new ContractParameter { Type = ContractParameterType.ByteArray, Value = item.GetByteArray() }); case Integer _: return(new ContractParameter { Type = ContractParameterType.Integer, Value = item.GetBigInteger() }); case InteropInterface _: return(new ContractParameter { Type = ContractParameterType.InteropInterface }); default: throw new ArgumentException(); } }
public static object FromStackItem(this StackItem item) { if (item is VM.Types.Integer) { return(item.GetBigInteger()); } else if (item is VM.Types.Boolean) { return(item.GetBoolean()); } else if (item is VM.Types.ByteArray) { return(item.GetByteArray()); } else { throw new NotImplementedException(); } }
internal static bool TryGetValue(this StackItem item, string type, out string value) { if (item != null && !string.IsNullOrEmpty(type)) { switch (type) { case "Boolean": value = item.GetBoolean().ToString(); return(true); case "Integer": value = item.GetBigInteger().ToString(); return(true); case "String": value = item.GetString(); return(true); } } value = string.Empty; return(false); }
public void TestTotalSupplyDecimal() { var snapshot = Blockchain.Singleton.GetSnapshot(); BigInteger totalSupply = 100_000_000; totalSupply *= test.Factor; StorageItem item = new StorageItem { Value = totalSupply.ToByteArrayStandard() }; var key = CreateStorageKey(Prefix_TotalSupply); key.Id = test.Id; snapshot.Storages.Add(key, item); ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, snapshot, 0); StackItem stackItem = test.TotalSupply(ae, null); stackItem.GetBigInteger().Should().Be(10_000_000_000_000_000); }
private static bool Crypto_CheckMultiSig(ApplicationEngine engine) { int n; byte[][] pubkeys; StackItem item = engine.CurrentContext.EvaluationStack.Pop(); if (item is VMArray array1) { pubkeys = array1.Select(p => p.GetByteArray()).ToArray(); n = pubkeys.Length; if (n == 0) { return(false); } } else { n = (int)item.GetBigInteger(); if (n < 1 || n > engine.CurrentContext.EvaluationStack.Count) { return(false); } pubkeys = new byte[n][]; for (int i = 0; i < n; i++) { pubkeys[i] = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); } } int m; byte[][] signatures; item = engine.CurrentContext.EvaluationStack.Pop(); if (item is VMArray array2) { signatures = array2.Select(p => p.GetByteArray()).ToArray(); m = signatures.Length; if (m == 0 || m > n) { return(false); } } else { m = (int)item.GetBigInteger(); if (m < 1 || m > n || m > engine.CurrentContext.EvaluationStack.Count) { return(false); } signatures = new byte[m][]; for (int i = 0; i < m; i++) { signatures[i] = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); } } byte[] message = engine.ScriptContainer.GetHashData(); bool fSuccess = true; try { for (int i = 0, j = 0; fSuccess && i < m && j < n;) { if (Crypto.Default.VerifySignature(message, signatures[i], pubkeys[j])) { i++; } j++; if (m - i > n - j) { fSuccess = false; } } } catch (ArgumentException) { fSuccess = false; } engine.CurrentContext.EvaluationStack.Push(fSuccess); return(true); }
private static bool Crypto_ECDsaCheckMultiSig(ApplicationEngine engine) { StackItem item0 = engine.CurrentContext.EvaluationStack.Pop(); ReadOnlySpan <byte> message = item0 switch { InteropInterface _interface => _interface.GetInterface <IVerifiable>().GetHashData(), Null _ => engine.ScriptContainer.GetHashData(), _ => item0.GetSpan() }; int n; byte[][] pubkeys; StackItem item = engine.CurrentContext.EvaluationStack.Pop(); if (item is Array array1) { pubkeys = array1.Select(p => p.GetSpan().ToArray()).ToArray(); n = pubkeys.Length; if (n == 0) { return(false); } } else { n = (int)item.GetBigInteger(); if (n < 1 || n > engine.CurrentContext.EvaluationStack.Count) { return(false); } pubkeys = new byte[n][]; for (int i = 0; i < n; i++) { pubkeys[i] = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); } } int m; byte[][] signatures; item = engine.CurrentContext.EvaluationStack.Pop(); if (item is Array array2) { signatures = array2.Select(p => p.GetSpan().ToArray()).ToArray(); m = signatures.Length; if (m == 0 || m > n) { return(false); } } else { m = (int)item.GetBigInteger(); if (m < 1 || m > n || m > engine.CurrentContext.EvaluationStack.Count) { return(false); } signatures = new byte[m][]; for (int i = 0; i < m; i++) { signatures[i] = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); } } bool fSuccess = true; try { for (int i = 0, j = 0; fSuccess && i < m && j < n;) { if (Cryptography.Crypto.VerifySignature(message, signatures[i], pubkeys[j])) { i++; } j++; if (m - i > n - j) { fSuccess = false; } } } catch (ArgumentException) { fSuccess = false; } engine.CurrentContext.EvaluationStack.Push(fSuccess); return(true); } }
public static string StackItemAsString(StackItem item, bool addQuotes = false, VMType hintType = VMType.Unknown) { if (item is ICollection) { var bytes = item.GetByteArray(); if (bytes != null && bytes.Length == 20) { var signatureHash = new UInt160(bytes); return(CryptoUtils.ToAddress(signatureHash)); } var s = new StringBuilder(); var items = (ICollection)item; s.Append('['); int i = 0; foreach (StackItem element in items) { if (i > 0) { s.Append(','); } s.Append(StackItemAsString(element)); i++; } s.Append(']'); return(s.ToString()); } if (item is VM.Types.Boolean && hintType == VMType.Unknown) { return(item.GetBoolean().ToString()); } if (item is VM.Types.Integer && hintType == VMType.Unknown) { return(item.GetBigInteger().ToString()); } if (item is VM.Types.InteropInterface) { var type = ((VM.Types.InteropInterface)item).GetInterfaceType(); return($"{type.Name}"); } byte[] data = null; try { data = item.GetByteArray(); } catch { } if ((data == null || data.Length == 0) && hintType == VMType.Unknown) { return("Null"); } if (hintType == VMType.Array) { var s = new StringBuilder(); s.Append('['); int count = 0; if (data.Length > 0) { var array = (VM.Types.Array)item; foreach (var entry in array) { if (count > 0) { s.Append(", "); } count++; s.Append(StackItemAsString(entry, addQuotes, VMType.Unknown)); } } s.Append(']'); return(s.ToString()); } return(FormattingUtils.OutputData(data, addQuotes, hintType)); }
private void ExecuteOp(OpCode opcode, ExecutionContext context) { if (opcode >= OpCode.PUSHBYTES1 && opcode <= OpCode.PUSHBYTES75) { context.EvaluationStack.Push(context.OpReader.ReadBytes((byte)opcode)); } else { switch (opcode) { // Push value case OpCode.PUSH0: context.EvaluationStack.Push(new byte[0]); break; case OpCode.PUSHDATA1: context.EvaluationStack.Push(context.OpReader.ReadBytes(context.OpReader.ReadByte())); break; case OpCode.PUSHDATA2: context.EvaluationStack.Push(context.OpReader.ReadBytes(context.OpReader.ReadUInt16())); break; case OpCode.PUSHDATA4: context.EvaluationStack.Push(context.OpReader.ReadBytes(context.OpReader.ReadInt32())); break; case OpCode.PUSHM1: case OpCode.PUSH1: case OpCode.PUSH2: case OpCode.PUSH3: case OpCode.PUSH4: case OpCode.PUSH5: case OpCode.PUSH6: case OpCode.PUSH7: case OpCode.PUSH8: case OpCode.PUSH9: case OpCode.PUSH10: case OpCode.PUSH11: case OpCode.PUSH12: case OpCode.PUSH13: case OpCode.PUSH14: case OpCode.PUSH15: case OpCode.PUSH16: context.EvaluationStack.Push((int)opcode - (int)OpCode.PUSH1 + 1); break; // Control case OpCode.NOP: break; case OpCode.JMP: case OpCode.JMPIF: case OpCode.JMPIFNOT: { int offset = context.OpReader.ReadInt16(); offset = context.InstructionPointer + offset - 3; if (offset < 0 || offset > context.Script.Length) { State |= VMState.FAULT; return; } bool fValue = true; if (opcode > OpCode.JMP) { fValue = context.EvaluationStack.Pop().GetBoolean(); if (opcode == OpCode.JMPIFNOT) { fValue = !fValue; } } if (fValue) { context.InstructionPointer = offset; } } break; case OpCode.CALL: { ExecutionContext contextCall = LoadScript(context.Script); context.EvaluationStack.CopyTo(contextCall.EvaluationStack); contextCall.InstructionPointer = context.InstructionPointer; context.EvaluationStack.Clear(); context.InstructionPointer += 2; ExecuteOp(OpCode.JMP, contextCall); } break; case OpCode.RET: using (ExecutionContext contextPop = InvocationStack.Pop()) { int rvcount = contextPop.RVCount; if (rvcount == -1) { rvcount = contextPop.EvaluationStack.Count; } if (rvcount > 0) { if (contextPop.EvaluationStack.Count < rvcount) { State |= VMState.FAULT; return; } RandomAccessStack <StackItem> stacEval = InvocationStack.Count == 0 ? ResultStack : CurrentContext.EvaluationStack; contextPop.EvaluationStack.CopyTo(stacEval, rvcount); } if (contextPop.RVCount == -1 && InvocationStack.Count > 0) { contextPop.AltStack.CopyTo(CurrentContext.AltStack); } } if (InvocationStack.Count == 0) { State |= VMState.HALT; } break; case OpCode.APPCALL: case OpCode.TAILCALL: { if (table == null) { State |= VMState.FAULT; return; } byte[] scriptHash = context.OpReader.ReadBytes(20); if (scriptHash.All(p => p == 0)) { scriptHash = context.EvaluationStack.Pop().GetByteArray(); } byte[] script = table.GetScript(scriptHash); if (script == null) { State |= VMState.FAULT; return; } ExecutionContext newContext = LoadScript(script); context.EvaluationStack.CopyTo(newContext.EvaluationStack); if (opcode == OpCode.TAILCALL) { InvocationStack.Remove(1).Dispose(); } else { context.EvaluationStack.Clear(); } } break; case OpCode.SYSCALL: if (!Service.Invoke(Encoding.ASCII.GetString(context.OpReader.ReadVarBytes(252)), this)) { State |= VMState.FAULT; } break; // Stack ops case OpCode.DUPFROMALTSTACK: context.EvaluationStack.Push(context.AltStack.Peek()); break; case OpCode.TOALTSTACK: context.AltStack.Push(context.EvaluationStack.Pop()); break; case OpCode.FROMALTSTACK: context.EvaluationStack.Push(context.AltStack.Pop()); break; case OpCode.XDROP: { int n = (int)context.EvaluationStack.Pop().GetBigInteger(); if (n < 0) { State |= VMState.FAULT; return; } context.EvaluationStack.Remove(n); } break; case OpCode.XSWAP: { int n = (int)context.EvaluationStack.Pop().GetBigInteger(); if (n < 0) { State |= VMState.FAULT; return; } if (n == 0) { break; } StackItem xn = context.EvaluationStack.Peek(n); context.EvaluationStack.Set(n, context.EvaluationStack.Peek()); context.EvaluationStack.Set(0, xn); } break; case OpCode.XTUCK: { int n = (int)context.EvaluationStack.Pop().GetBigInteger(); if (n <= 0) { State |= VMState.FAULT; return; } context.EvaluationStack.Insert(n, context.EvaluationStack.Peek()); } break; case OpCode.DEPTH: context.EvaluationStack.Push(context.EvaluationStack.Count); break; case OpCode.DROP: context.EvaluationStack.Pop(); break; case OpCode.DUP: context.EvaluationStack.Push(context.EvaluationStack.Peek()); break; case OpCode.NIP: context.EvaluationStack.Remove(1); break; case OpCode.OVER: context.EvaluationStack.Push(context.EvaluationStack.Peek(1)); break; case OpCode.PICK: { int n = (int)context.EvaluationStack.Pop().GetBigInteger(); if (n < 0) { State |= VMState.FAULT; return; } context.EvaluationStack.Push(context.EvaluationStack.Peek(n)); } break; case OpCode.ROLL: { int n = (int)context.EvaluationStack.Pop().GetBigInteger(); if (n < 0) { State |= VMState.FAULT; return; } if (n == 0) { break; } context.EvaluationStack.Push(context.EvaluationStack.Remove(n)); } break; case OpCode.ROT: context.EvaluationStack.Push(context.EvaluationStack.Remove(2)); break; case OpCode.SWAP: context.EvaluationStack.Push(context.EvaluationStack.Remove(1)); break; case OpCode.TUCK: context.EvaluationStack.Insert(2, context.EvaluationStack.Peek()); break; case OpCode.CAT: { byte[] x2 = context.EvaluationStack.Pop().GetByteArray(); byte[] x1 = context.EvaluationStack.Pop().GetByteArray(); context.EvaluationStack.Push(x1.Concat(x2).ToArray()); } break; case OpCode.SUBSTR: { int count = (int)context.EvaluationStack.Pop().GetBigInteger(); if (count < 0) { State |= VMState.FAULT; return; } int index = (int)context.EvaluationStack.Pop().GetBigInteger(); if (index < 0) { State |= VMState.FAULT; return; } byte[] x = context.EvaluationStack.Pop().GetByteArray(); context.EvaluationStack.Push(x.Skip(index).Take(count).ToArray()); } break; case OpCode.LEFT: { int count = (int)context.EvaluationStack.Pop().GetBigInteger(); if (count < 0) { State |= VMState.FAULT; return; } byte[] x = context.EvaluationStack.Pop().GetByteArray(); context.EvaluationStack.Push(x.Take(count).ToArray()); } break; case OpCode.RIGHT: { int count = (int)context.EvaluationStack.Pop().GetBigInteger(); if (count < 0) { State |= VMState.FAULT; return; } byte[] x = context.EvaluationStack.Pop().GetByteArray(); if (x.Length < count) { State |= VMState.FAULT; return; } context.EvaluationStack.Push(x.Skip(x.Length - count).ToArray()); } break; case OpCode.SIZE: { byte[] x = context.EvaluationStack.Pop().GetByteArray(); context.EvaluationStack.Push(x.Length); } break; // Bitwise logic case OpCode.INVERT: { BigInteger x = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(~x); } break; case OpCode.AND: { BigInteger x2 = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x1 = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x1 & x2); } break; case OpCode.OR: { BigInteger x2 = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x1 = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x1 | x2); } break; case OpCode.XOR: { BigInteger x2 = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x1 = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x1 ^ x2); } break; case OpCode.EQUAL: { StackItem x2 = context.EvaluationStack.Pop(); StackItem x1 = context.EvaluationStack.Pop(); context.EvaluationStack.Push(x1.Equals(x2)); } break; // Numeric case OpCode.INC: { BigInteger x = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x + 1); } break; case OpCode.DEC: { BigInteger x = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x - 1); } break; case OpCode.SIGN: { BigInteger x = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x.Sign); } break; case OpCode.NEGATE: { BigInteger x = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(-x); } break; case OpCode.ABS: { BigInteger x = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(BigInteger.Abs(x)); } break; case OpCode.NOT: { bool x = context.EvaluationStack.Pop().GetBoolean(); context.EvaluationStack.Push(!x); } break; case OpCode.NZ: { BigInteger x = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x != BigInteger.Zero); } break; case OpCode.ADD: { BigInteger x2 = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x1 = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x1 + x2); } break; case OpCode.SUB: { BigInteger x2 = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x1 = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x1 - x2); } break; case OpCode.MUL: { BigInteger x2 = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x1 = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x1 * x2); } break; case OpCode.DIV: { BigInteger x2 = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x1 = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x1 / x2); } break; case OpCode.MOD: { BigInteger x2 = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x1 = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x1 % x2); } break; case OpCode.SHL: { int n = (int)context.EvaluationStack.Pop().GetBigInteger(); BigInteger x = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x << n); } break; case OpCode.SHR: { int n = (int)context.EvaluationStack.Pop().GetBigInteger(); BigInteger x = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x >> n); } break; case OpCode.BOOLAND: { bool x2 = context.EvaluationStack.Pop().GetBoolean(); bool x1 = context.EvaluationStack.Pop().GetBoolean(); context.EvaluationStack.Push(x1 && x2); } break; case OpCode.BOOLOR: { bool x2 = context.EvaluationStack.Pop().GetBoolean(); bool x1 = context.EvaluationStack.Pop().GetBoolean(); context.EvaluationStack.Push(x1 || x2); } break; case OpCode.NUMEQUAL: { BigInteger x2 = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x1 = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x1 == x2); } break; case OpCode.NUMNOTEQUAL: { BigInteger x2 = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x1 = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x1 != x2); } break; case OpCode.LT: { BigInteger x2 = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x1 = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x1 < x2); } break; case OpCode.GT: { BigInteger x2 = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x1 = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x1 > x2); } break; case OpCode.LTE: { BigInteger x2 = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x1 = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x1 <= x2); } break; case OpCode.GTE: { BigInteger x2 = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x1 = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(x1 >= x2); } break; case OpCode.MIN: { BigInteger x2 = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x1 = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(BigInteger.Min(x1, x2)); } break; case OpCode.MAX: { BigInteger x2 = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x1 = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(BigInteger.Max(x1, x2)); } break; case OpCode.WITHIN: { BigInteger b = context.EvaluationStack.Pop().GetBigInteger(); BigInteger a = context.EvaluationStack.Pop().GetBigInteger(); BigInteger x = context.EvaluationStack.Pop().GetBigInteger(); context.EvaluationStack.Push(a <= x && x < b); } break; // Crypto case OpCode.SHA1: using (SHA1 sha = SHA1.Create()) { byte[] x = context.EvaluationStack.Pop().GetByteArray(); context.EvaluationStack.Push(sha.ComputeHash(x)); } break; case OpCode.SHA256: using (SHA256 sha = SHA256.Create()) { byte[] x = context.EvaluationStack.Pop().GetByteArray(); context.EvaluationStack.Push(sha.ComputeHash(x)); } break; case OpCode.HASH160: { byte[] x = context.EvaluationStack.Pop().GetByteArray(); context.EvaluationStack.Push(Crypto.Hash160(x)); } break; case OpCode.HASH256: { byte[] x = context.EvaluationStack.Pop().GetByteArray(); context.EvaluationStack.Push(Crypto.Hash256(x)); } break; case OpCode.CHECKSIG: { byte[] pubkey = context.EvaluationStack.Pop().GetByteArray(); byte[] signature = context.EvaluationStack.Pop().GetByteArray(); try { context.EvaluationStack.Push(Crypto.VerifySignature(ScriptContainer.GetMessage(), signature, pubkey)); } catch (ArgumentException) { context.EvaluationStack.Push(false); } } break; case OpCode.VERIFY: { byte[] pubkey = context.EvaluationStack.Pop().GetByteArray(); byte[] signature = context.EvaluationStack.Pop().GetByteArray(); byte[] message = context.EvaluationStack.Pop().GetByteArray(); try { context.EvaluationStack.Push(Crypto.VerifySignature(message, signature, pubkey)); } catch (ArgumentException) { context.EvaluationStack.Push(false); } } break; case OpCode.CHECKMULTISIG: { int n; byte[][] pubkeys; StackItem item = context.EvaluationStack.Pop(); if (item is VMArray array1) { pubkeys = array1.Select(p => p.GetByteArray()).ToArray(); n = pubkeys.Length; if (n == 0) { State |= VMState.FAULT; return; } } else { n = (int)item.GetBigInteger(); if (n < 1 || n > context.EvaluationStack.Count) { State |= VMState.FAULT; return; } pubkeys = new byte[n][]; for (int i = 0; i < n; i++) { pubkeys[i] = context.EvaluationStack.Pop().GetByteArray(); } } int m; byte[][] signatures; item = context.EvaluationStack.Pop(); if (item is VMArray array2) { signatures = array2.Select(p => p.GetByteArray()).ToArray(); m = signatures.Length; if (m == 0 || m > n) { State |= VMState.FAULT; return; } } else { m = (int)item.GetBigInteger(); if (m < 1 || m > n || m > context.EvaluationStack.Count) { State |= VMState.FAULT; return; } signatures = new byte[m][]; for (int i = 0; i < m; i++) { signatures[i] = context.EvaluationStack.Pop().GetByteArray(); } } byte[] message = ScriptContainer.GetMessage(); bool fSuccess = true; try { for (int i = 0, j = 0; fSuccess && i < m && j < n;) { if (Crypto.VerifySignature(message, signatures[i], pubkeys[j])) { i++; } j++; if (m - i > n - j) { fSuccess = false; } } } catch (ArgumentException) { fSuccess = false; } context.EvaluationStack.Push(fSuccess); } break; // Array case OpCode.ARRAYSIZE: { StackItem item = context.EvaluationStack.Pop(); if (item is ICollection collection) { context.EvaluationStack.Push(collection.Count); } else { context.EvaluationStack.Push(item.GetByteArray().Length); } } break; case OpCode.PACK: { int size = (int)context.EvaluationStack.Pop().GetBigInteger(); if (size < 0 || size > context.EvaluationStack.Count) { State |= VMState.FAULT; return; } List <StackItem> items = new List <StackItem>(size); for (int i = 0; i < size; i++) { items.Add(context.EvaluationStack.Pop()); } context.EvaluationStack.Push(items); } break; case OpCode.UNPACK: { StackItem item = context.EvaluationStack.Pop(); if (item is VMArray array) { for (int i = array.Count - 1; i >= 0; i--) { context.EvaluationStack.Push(array[i]); } context.EvaluationStack.Push(array.Count); } else { State |= VMState.FAULT; return; } } break; case OpCode.PICKITEM: { StackItem key = context.EvaluationStack.Pop(); if (key is ICollection) { State |= VMState.FAULT; return; } switch (context.EvaluationStack.Pop()) { case VMArray array: int index = (int)key.GetBigInteger(); if (index < 0 || index >= array.Count) { State |= VMState.FAULT; return; } context.EvaluationStack.Push(array[index]); break; case Map map: if (map.TryGetValue(key, out StackItem value)) { context.EvaluationStack.Push(value); } else { State |= VMState.FAULT; return; } break; default: State |= VMState.FAULT; return; } } break; case OpCode.SETITEM: { StackItem value = context.EvaluationStack.Pop(); if (value is Struct s) { value = s.Clone(); } StackItem key = context.EvaluationStack.Pop(); if (key is ICollection) { State |= VMState.FAULT; return; } switch (context.EvaluationStack.Pop()) { case VMArray array: int index = (int)key.GetBigInteger(); if (index < 0 || index >= array.Count) { State |= VMState.FAULT; return; } array[index] = value; break; case Map map: map[key] = value; break; default: State |= VMState.FAULT; return; } } break; case OpCode.NEWARRAY: { int count = (int)context.EvaluationStack.Pop().GetBigInteger(); List <StackItem> items = new List <StackItem>(count); for (var i = 0; i < count; i++) { items.Add(false); } context.EvaluationStack.Push(new VMArray(items)); } break; case OpCode.NEWSTRUCT: { int count = (int)context.EvaluationStack.Pop().GetBigInteger(); List <StackItem> items = new List <StackItem>(count); for (var i = 0; i < count; i++) { items.Add(false); } context.EvaluationStack.Push(new Base.Types.Struct(items)); } break; case OpCode.NEWMAP: context.EvaluationStack.Push(new Map()); break; case OpCode.APPEND: { StackItem newItem = context.EvaluationStack.Pop(); if (newItem is Base.Types.Struct s) { newItem = s.Clone(); } StackItem arrItem = context.EvaluationStack.Pop(); if (arrItem is VMArray array) { array.Add(newItem); } else { State |= VMState.FAULT; return; } } break; case OpCode.REVERSE: { StackItem arrItem = context.EvaluationStack.Pop(); if (arrItem is VMArray array) { array.Reverse(); } else { State |= VMState.FAULT; return; } } break; case OpCode.REMOVE: { StackItem key = context.EvaluationStack.Pop(); if (key is ICollection) { State |= VMState.FAULT; return; } switch (context.EvaluationStack.Pop()) { case VMArray array: int index = (int)key.GetBigInteger(); if (index < 0 || index >= array.Count) { State |= VMState.FAULT; return; } array.RemoveAt(index); break; case Map map: map.Remove(key); break; default: State |= VMState.FAULT; return; } } break; case OpCode.HASKEY: { StackItem key = context.EvaluationStack.Pop(); if (key is ICollection) { State |= VMState.FAULT; return; } switch (context.EvaluationStack.Pop()) { case VMArray array: int index = (int)key.GetBigInteger(); if (index < 0) { State |= VMState.FAULT; return; } context.EvaluationStack.Push(index < array.Count); break; case Map map: context.EvaluationStack.Push(map.ContainsKey(key)); break; default: State |= VMState.FAULT; return; } } break; case OpCode.KEYS: switch (context.EvaluationStack.Pop()) { case Map map: context.EvaluationStack.Push(new VMArray(map.Keys)); break; default: State |= VMState.FAULT; return; } break; case OpCode.VALUES: { ICollection <StackItem> values; switch (context.EvaluationStack.Pop()) { case VMArray array: values = array; break; case Map map: values = map.Values; break; default: State |= VMState.FAULT; return; } List <StackItem> newArray = new List <StackItem>(values.Count); foreach (StackItem item in values) { if (item is Struct s) { newArray.Add(s.Clone()); } else { newArray.Add(item); } } context.EvaluationStack.Push(new VMArray(newArray)); } break; // Stack isolation case OpCode.CALL_I: { int rvcount = context.OpReader.ReadByte(); int pcount = context.OpReader.ReadByte(); if (context.EvaluationStack.Count < pcount) { State |= VMState.FAULT; return; } ExecutionContext contextCall = LoadScript(context.Script, rvcount); context.EvaluationStack.CopyTo(contextCall.EvaluationStack, pcount); contextCall.InstructionPointer = context.InstructionPointer; for (int i = 0; i < pcount; i++) { context.EvaluationStack.Pop(); } context.InstructionPointer += 2; ExecuteOp(OpCode.JMP, contextCall); } break; case OpCode.CALL_E: case OpCode.CALL_ED: case OpCode.CALL_ET: case OpCode.CALL_EDT: { if (table == null) { State |= VMState.FAULT; return; } int rvcount = context.OpReader.ReadByte(); int pcount = context.OpReader.ReadByte(); if (context.EvaluationStack.Count < pcount) { State |= VMState.FAULT; return; } if (opcode == OpCode.CALL_ET || opcode == OpCode.CALL_EDT) { if (context.RVCount != rvcount) { State |= VMState.FAULT; return; } } byte[] scriptHash; if (opcode == OpCode.CALL_ED || opcode == OpCode.CALL_EDT) { scriptHash = context.EvaluationStack.Pop().GetByteArray(); } else { scriptHash = context.OpReader.ReadBytes(20); } byte[] script = table.GetScript(scriptHash); if (script == null) { State |= VMState.FAULT; return; } ExecutionContext contextNew = LoadScript(script, rvcount); context.EvaluationStack.CopyTo(contextNew.EvaluationStack, pcount); if (opcode == OpCode.CALL_ET || opcode == OpCode.CALL_EDT) { InvocationStack.Remove(1).Dispose(); } else { for (int i = 0; i < pcount; i++) { context.EvaluationStack.Pop(); } } } break; // Exceptions case OpCode.THROW: State |= VMState.FAULT; return; case OpCode.THROWIFNOT: if (!context.EvaluationStack.Pop().GetBoolean()) { State |= VMState.FAULT; return; } break; default: State |= VMState.FAULT; return; } } if (!State.HasFlag(VMState.FAULT) && InvocationStack.Count > 0) { if (breakPoints.TryGetValue(CurrentContext.ScriptHash, out HashSet <uint> hashset) && hashset.Contains((uint)CurrentContext.InstructionPointer)) { State |= VMState.BREAK; } } }
public static string StackItemAsString(StackItem item, bool addQuotes = false, Emulator.Type hintType = Emulator.Type.Unknown) { if (item is ICollection && !(item is Map)) { var bytes = item.GetByteArray(); if (bytes != null && bytes.Length == 20) { var signatureHash = new UInt160(bytes); return(CryptoUtils.ToAddress(signatureHash)); } var s = new StringBuilder(); var items = (ICollection)item; s.Append('['); int i = 0; foreach (StackItem element in items) { if (i > 0) { s.Append(','); } s.Append(StackItemAsString(element)); i++; } s.Append(']'); return(s.ToString()); } else if (item is Map) { Map mapItem = (Map)item; var builder = new StringBuilder(); builder.Append("{\n"); foreach (var key in mapItem.Keys) { builder.Append(StackItemAsString(key)); builder.Append(" : "); builder.Append(StackItemAsString(mapItem[key])); builder.Append("\n"); } builder.Append("}"); return(builder.ToString()); } if (item is Neo.VM.Types.Boolean && hintType == Emulator.Type.Unknown) { return(item.GetBoolean().ToString()); } if (item is Neo.VM.Types.Integer && hintType == Emulator.Type.Unknown) { return(item.GetBigInteger().ToString()); } if (item is Neo.VM.Types.InteropInterface) { return("{InteropInterface}"); } byte[] data = null; try { data = item.GetByteArray(); } catch { } if ((data == null || data.Length == 0) && hintType == Emulator.Type.Unknown) { return("Null"); } if (hintType == Emulator.Type.Array) { var s = new StringBuilder(); s.Append('['); int count = 0; if (data.Length > 0) { var array = (VM.Types.Array)item; foreach (var entry in array) { if (count > 0) { s.Append(", "); } count++; s.Append(StackItemAsString(entry, addQuotes, Emulator.Type.Unknown)); } } s.Append(']'); return(s.ToString()); } return(FormattingUtils.OutputData(data, addQuotes, hintType)); }
public static string StackItemAsString(StackItem item, bool addQuotes = false, Emulator.Type hintType = Emulator.Type.Unknown) { if (item is ICollection) { var bytes = item.GetByteArray(); if (bytes != null && bytes.Length == 20) { var signatureHash = new UInt160(bytes); return(Crypto.Default.ToAddress(signatureHash)); } var s = new StringBuilder(); var items = (ICollection)item; s.Append('['); int i = 0; foreach (StackItem element in items) { if (i > 0) { s.Append(','); } s.Append(StackItemAsString(element)); i++; } s.Append(']'); return(s.ToString()); } if (item is Neo.VM.Types.Boolean && hintType == Emulator.Type.Unknown) { return(item.GetBoolean().ToString()); } if (item is Neo.VM.Types.Integer && hintType == Emulator.Type.Unknown) { return(item.GetBigInteger().ToString()); } if (item is Neo.VM.Types.InteropInterface) { return("{InteropInterface}"); } byte[] data = null; try { data = item.GetByteArray(); } catch { } if ((data == null || data.Length == 0) && hintType == Emulator.Type.Unknown) { return("Null"); } return(FormattingUtils.OutputData(data, addQuotes, hintType)); }
public override bool Verify(IEnumerable <Transaction> mempool) { try { string assetName; ExecutionEngine engine = new ExecutionEngine(this, Cryptography.Crypto.Default); Dictionary <CultureInfo, string> _names; CultureInfo culture = null; engine.LoadScript(this.Script, false); engine.Execute(); if (engine.EvaluationStack.Count == 0) { return(false); } StackItem val = engine.EvaluationStack.Pop(); AssetType asset_type = (AssetType)(byte)val.GetBigInteger(); if (!Enum.IsDefined(typeof(AssetType), asset_type) || asset_type == AssetType.CreditFlag || asset_type == AssetType.DutyFlag || asset_type == AssetType.GoverningToken || asset_type == AssetType.UtilityToken) { return(false); } string name = Encoding.UTF8.GetString(engine.EvaluationStack.Pop().GetByteArray()); JObject name_obj; try { name_obj = JObject.Parse(name); } catch (FormatException) { name_obj = name; } if (name_obj is JString) { _names = new Dictionary <CultureInfo, string> { { new CultureInfo("en"), name_obj.AsString() } } } ; else { _names = ((JArray)JObject.Parse(name)).ToDictionary(p => new CultureInfo(p["lang"].AsString()), p => p["name"].AsString()); } if (culture == null) { culture = CultureInfo.CurrentCulture; } if (_names.TryGetValue(culture, out assetName)) { } else if (_names.TryGetValue(new CultureInfo("en"), out assetName)) { } else { assetName = _names.Values.First(); } if (isDuplicatedToken(assetName)) { return(false); } } catch (Exception ex) { } if (Gas.GetData() % 100000000 != 0) { return(false); } return(base.Verify(mempool)); }
public void CastTest() { // Signed integer StackItem item = int.MaxValue; Assert.IsInstanceOfType(item, typeof(Integer)); Assert.AreEqual(new BigInteger(int.MaxValue), item.GetBigInteger()); // Unsigned integer item = uint.MaxValue; Assert.IsInstanceOfType(item, typeof(Integer)); Assert.AreEqual(new BigInteger(uint.MaxValue), item.GetBigInteger()); // Signed long item = long.MaxValue; Assert.IsInstanceOfType(item, typeof(Integer)); Assert.AreEqual(new BigInteger(long.MaxValue), item.GetBigInteger()); // Unsigned long item = ulong.MaxValue; Assert.IsInstanceOfType(item, typeof(Integer)); Assert.AreEqual(new BigInteger(ulong.MaxValue), item.GetBigInteger()); // BigInteger item = BigInteger.MinusOne; Assert.IsInstanceOfType(item, typeof(Integer)); Assert.AreEqual(new BigInteger(-1), item.GetBigInteger()); // Boolean item = true; Assert.IsInstanceOfType(item, typeof(Boolean)); Assert.IsTrue(item.GetBoolean()); // ByteArray item = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }; Assert.IsInstanceOfType(item, typeof(ByteArray)); CollectionAssert.AreEqual(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }, item.GetByteArray()); // String item = "NEO - 种智能经济分布式网络"; Assert.IsInstanceOfType(item, typeof(ByteArray)); CollectionAssert.AreEqual(Encoding.UTF8.GetBytes("NEO - 种智能经济分布式网络"), item.GetByteArray()); Assert.AreEqual("NEO - 种智能经济分布式网络", item.GetString()); // Array item = new StackItem[] { true, false }; Assert.IsInstanceOfType(item, typeof(Array)); Assert.IsTrue(((Array)item)[0].GetBoolean()); Assert.IsFalse(((Array)item)[1].GetBoolean()); // List item = new List <StackItem>(new StackItem[] { true, false }); Assert.IsInstanceOfType(item, typeof(Array)); Assert.IsTrue(((Array)item)[0].GetBoolean()); Assert.IsFalse(((Array)item)[1].GetBoolean()); // Interop var interop = new InteropInterface <Dictionary <int, int> >(new Dictionary <int, int>() { { 1, 1 } }); Dictionary <int, int> value = interop; Assert.AreEqual(1, value.Count); }
/// <summary> /// Get Printable version /// </summary> /// <param name="value">Value</param> object GetPrintable(StackItem value) { if (value == null) { return("NULL"); } else { Type tp = value.GetType(); switch (tp.FullName) { case "Neo.VM.Types.Boolean": return(value.GetBoolean()); case "Neo.VM.Types.ByteArray": { byte[] v = value.GetByteArray(); if (v == null || v.Length == 0) { return("[0]"); } if (v.Length > 200) { return("[" + v.Length.ToString() + "] ..."); } return("[" + v.Length.ToString() + "] 0x" + v.ToHexString()); } case "Neo.VM.Types.Integer": { BigInteger v = value.GetBigInteger(); if (v.Sign >= 0 && v > ulong.MaxValue) { return("[BigInteger] ..."); } else if (v.Sign < 0 && v < long.MinValue) { return("[-BigInteger] ..."); } return(v.ToString()); } case "Neo.VM.Types.Struct": case "Neo.VM.Types.Array": { Neo.VM.Types.Array ar = value as Neo.VM.Types.Array; StackItem[] si = ar.ToArray(); if (si.Length > 200) { return("[" + si.Length.ToString() + "] ..."); } return ("[" + si.Length + "]" + JsonHelper.Serialize(si.Select(u => GetPrintable(u)).ToArray(), true, false)); } case "Neo.VM.Types.InteropInterface": { if (_Interop == null) { _Interop = tp.GetField("_object", BindingFlags.Instance | BindingFlags.NonPublic); foreach (Type txp in typeof(ApplicationEngine).Assembly.GetTypes()) { // Extract internal type if (txp.FullName == "Neo.SmartContract.StorageContext") { _StorageContext = txp; _StorageContextToArray = txp.GetMethod("ToArray"); break; } } } object ob = _Interop.GetValue(value); if (ob != null && ob.GetType() == _StorageContext) { ob = _StorageContextToArray.Invoke(ob, new object[] { }); } else { } //if (ob !=null && ob is UInt160 a) return(JsonHelper.Serialize(ob, true, false)); } default: { break; } } } return(""); }
private static ContractParameter ToParameter(StackItem item, List <Tuple <StackItem, ContractParameter> > context) { ContractParameter parameter = null; switch (item) { case VMArray array: if (context is null) { context = new List <Tuple <StackItem, ContractParameter> >(); } else { parameter = context.FirstOrDefault(p => ReferenceEquals(p.Item1, item))?.Item2; } if (parameter is null) { parameter = new ContractParameter { Type = ContractParameterType.Array }; context.Add(new Tuple <StackItem, ContractParameter>(item, parameter)); parameter.Value = array.Select(p => ToParameter(p, context)).ToList(); } break; case Map map: if (context is null) { context = new List <Tuple <StackItem, ContractParameter> >(); } else { parameter = context.FirstOrDefault(p => ReferenceEquals(p.Item1, item))?.Item2; } if (parameter is null) { parameter = new ContractParameter { Type = ContractParameterType.Map }; context.Add(new Tuple <StackItem, ContractParameter>(item, parameter)); parameter.Value = map.Select(p => new KeyValuePair <ContractParameter, ContractParameter>(ToParameter(p.Key, context), ToParameter(p.Value, context))).ToList(); } break; case VMBoolean _: parameter = new ContractParameter { Type = ContractParameterType.Boolean, Value = item.GetBoolean() }; break; case ByteArray _: parameter = new ContractParameter { Type = ContractParameterType.ByteArray, Value = item.GetByteArray() }; break; case Integer _: parameter = new ContractParameter { Type = ContractParameterType.Integer, Value = item.GetBigInteger() }; break; case InteropContract _: parameter = new ContractParameter { Type = ContractParameterType.InteropInterface }; break; default: throw new ArgumentException(); } return(parameter); }