public ChainListener(NeoAPI api, Transaction deployTx, uint lastBlock, Logger logger) { this.neo_api = api; this.lastBlock = lastBlock; this.logger = logger; if (deployTx != null) { var code = NeoTools.Disassemble(deployTx.script); for (int i = 1; i < code.Count; i++) { var entry = code[i]; if (entry.opcode == OpCode.SYSCALL && entry.data != null) { var method = Encoding.ASCII.GetString(entry.data); if (method == "Neo.Contract.Create") { var prev = code[i - 1]; this.contract_bytecode = prev.data; this.contract_hash = contract_bytecode.ToScriptHash(); break; } } } } else { throw new Exception($"Invalid deploy transaction"); } }
public NeoEventMonitor1(NeoAPI api, Transaction deployTx, uint startBlock) { this._api = api; this._startBlock = startBlock; this._listenerVM = new SnapshotVM(this); List <AVMInstruction> deployTxScript = NeoTools.Disassemble(deployTx.script); for (int i = 1; i < deployTxScript.Count; i++) { var instruction = deployTxScript[i]; if (instruction.opcode == OpCode.SYSCALL && instruction.data != null) { var method = Encoding.ASCII.GetString(instruction.data); if (method == "Neo.Contract.Create") { Console.WriteLine($"method == Neo.Contract.Create"); var prevInstruction = deployTxScript[i - 1]; this._contractBytecode = prevInstruction.data; this._contractScriptHash = _contractBytecode.ToScriptHash(); Console.WriteLine($"_contractBytecode: {_contractBytecode.Length}\tcontractScriptHash: {this._contractScriptHash.ToString()}"); break; } } } }
private bool ProcessIncomingBlock(uint height) { //Console.WriteLine($"Processing block {height}..."); var block = _api.GetBlock(height); if (block == null) { Console.WriteLine($"WARNING: could not fetch block #{height}"); return(false); } foreach (var tx in block.transactions) { Console.WriteLine($"{height} Processing tx {tx.Hash}..."); //if (tx.type != TransactionType.InvocationTransaction) //{ // continue; //} List <AVMInstruction> ops; try { ops = NeoTools.Disassemble(tx.script); Console.WriteLine($"{height} Processing tx {tx.Hash} has {tx.script.Length} byte codes"); } catch { continue; } //ProcessNotifications(height, tx); for (int i = 0; i < ops.Count; i++) { var op = ops[i]; if (op.opcode == OpCode.APPCALL && op.data != null && op.data.Length == 20) { var scriptHash = new UInt160(op.data); var engine = new ExecutionEngine(tx, _listenerVM, _listenerVM); engine.LoadScript(tx.script); engine.Execute(null /*x => * { * debugger.Step(x); * }*/ ); ProcessNotifications(height, tx); } } } //Console.WriteLine($"Processing block {height} success"); return(true); }
private void ProcessIncomingBlock(uint height) { var block = neo_api.GetBlock(height); if (block == null) { throw new Exception($"API failure, could not fetch block #{height}"); } foreach (var tx in block.transactions) { if (tx.type != TransactionType.InvocationTransaction) { continue; } List <AVMInstruction> ops; try { ops = NeoTools.Disassemble(tx.script); } catch { continue; } for (int i = 0; i < ops.Count; i++) { var op = ops[i]; // opcode data must contain the script hash to the Bluzelle contract, otherwise ignore it if (op.opcode == OpCode.APPCALL && op.data != null && op.data.Length == 20) { var scriptHash = new UInt160(op.data); if (scriptHash != bluzelle_contract_hash) { continue; } var engine = new ExecutionEngine(tx, listenerVM, listenerVM); engine.LoadScript(tx.script); engine.Execute(null /*x => * { * debugger.Step(x); * }*/ ); ProcessNotifications(tx); } } } }
public Contract(byte[] script) { this.script = script; this.instructions = NeoTools.Disassemble(script).ToArray(); this.scriptHash = script.ToScriptHash(); }
private void ProcessIncomingBlock(uint height) { var block = neo_api.GetBlock(height); if (block == null) { return; } Console.WriteLine($"Processing block {height}"); foreach (var tx in block.transactions) { if (tx.type != TransactionType.InvocationTransaction) { continue; } List <AVMInstruction> ops; try { ops = NeoTools.Disassemble(tx.script); } catch { continue; } for (int i = 0; i < ops.Count; i++) { var op = ops[i]; // opcode data must contain the script hash to the Bluzelle contract, otherwise ignore it if (op.opcode == OpCode.APPCALL && op.data != null && op.data.Length == 20) { var scriptHash = new UInt160(op.data); if (scriptHash != bluzelle_contract_hash) { continue; } Console.WriteLine($"Found Bluzelle call in tx {tx.Hash}"); var operation = Encoding.ASCII.GetString(ops[i - 1].data); int index = i - 3; var argCount = 1 + ((byte)ops[index].opcode - (byte)OpCode.PUSH1); var args = new List <object>(); while (argCount > 0) { index--; if (ops[index].opcode >= OpCode.PUSHBYTES1 && ops[index].opcode <= OpCode.PUSHBYTES75) { args.Add(ops[index].data); } else if (ops[index].opcode >= OpCode.PUSH1 && ops[index].opcode <= OpCode.PUSH16) { var n = new BigInteger(1 + (ops[index].opcode - OpCode.PUSH1)); args.Add(n); } else if (ops[index].opcode == OpCode.PUSH0) { args.Add(new BigInteger(0)); } else if (ops[index].opcode == OpCode.PUSHM1) { args.Add(new BigInteger(-1)); } else { throw new Exception("Invalid arg type"); } argCount--; } switch (operation) { case "create": { try { var uuid = Encoding.ASCII.GetString((byte[])args[1]); var key = Encoding.ASCII.GetString((byte[])args[2]); var value = Encoding.ASCII.GetString((byte[])args[3]); Console.WriteLine($"CREATE ({uuid},{key},{value})"); this.swarm.Create(uuid, key, value); } catch { Console.WriteLine($"Failed decoding args for tx {tx.Hash}"); } break; } case "delete": { try { var uuid = Encoding.ASCII.GetString((byte[])args[1]); var key = Encoding.ASCII.GetString((byte[])args[2]); Console.WriteLine($"DELETE ({uuid},{key})"); this.swarm.Delete(uuid, key); } catch { Console.WriteLine($"Failed decoding args for tx {tx.Hash}"); } break; } case "update": { try { var uuid = Encoding.ASCII.GetString((byte[])args[1]); var key = Encoding.ASCII.GetString((byte[])args[2]); var value = Encoding.ASCII.GetString((byte[])args[3]); Console.WriteLine($"UPDATE ({uuid},{key},{value})"); this.swarm.Update(uuid, key, value); } catch { Console.WriteLine($"Failed decoding args for tx {tx.Hash}"); } break; } case "read": { try { var uuid = Encoding.ASCII.GetString((byte[])args[1]); var key = Encoding.ASCII.GetString((byte[])args[2]); Console.WriteLine($"READ ({uuid},{key})"); var val = this.swarm.Read(uuid, key); /* * string id = null; * var push_tx = neo_api.CallContract(owner_keys, bluzelle_contract_hash, "push", new object[] {id, val }); * neo_api.WaitForTransaction(owner_keys, push_tx);*/ } catch { // Console.WriteLine($"Failed decoding args for tx {tx.Hash}"); } break; } } break; } } } }
public void Execute(NEP5 token, byte[] token_script, Action <SnapshotVM> visitor) { if (token_script == null) { throw new Exception("Could not find token script"); } var script_hash = token_script.ToScriptHash(); if (script_hash != token.scriptHash) { throw new Exception("Invalid script code, does not match the token scripthash"); } var api = token.api; var balances = new Dictionary <UInt160, decimal>(); var vm = new SnapshotVM(this); vm.AddScript(token_script); var debugger = new DebugClient(); debugger.SendScript(token_script); IEnumerable <Block> sorted_blocks = blocks.Values.OrderBy(x => x.Date); foreach (var block in sorted_blocks) { vm.SetCurrentBlock(block); bool executed = false; foreach (var tx in block.transactions) { switch (tx.type) { case TransactionType.InvocationTransaction: { List <AVMInstruction> ops; try { ops = NeoTools.Disassemble(tx.script); } catch { continue; } for (int i = 0; i < ops.Count; i++) { var op = ops[i]; if (op.opcode == OpCode.APPCALL && op.data != null && op.data.Length == 20) { var scriptHash = new UInt160(op.data); if (scriptHash != token.scriptHash) { continue; } var engine = new ExecutionEngine(tx, vm, vm); engine.LoadScript(tx.script); engine.Execute( x => { debugger.Step(x); } ); executed = true; } } break; } } } if (executed) { visitor(vm); } } }
public Snapshot(NEP5 token, uint startBlock, uint endBlock = 0) { var api = token.api; if (endBlock == 0) { endBlock = api.GetBlockHeight(); } if (endBlock < startBlock) { throw new ArgumentException("End block cannot be smaller than start block"); } for (uint height = startBlock; height <= endBlock; height++) { var block = api.GetBlock(height); var snapCount = 0; foreach (var tx in block.transactions) { switch (tx.type) { case TransactionType.ContractTransaction: { foreach (var output in tx.outputs) { if (output.scriptHash == token.scriptHash) { MergeTransaction(api, tx); snapCount++; break; } } break; } case TransactionType.InvocationTransaction: { List <AVMInstruction> ops; try { ops = NeoTools.Disassemble(tx.script); } catch { continue; } for (int i = 0; i < ops.Count; i++) { var op = ops[i]; if (op.opcode == OpCode.APPCALL && op.data != null && op.data.Length == 20) { var scriptHash = new UInt160(op.data); if (scriptHash == token.scriptHash) { MergeTransaction(api, tx); snapCount++; break; } } } break; } } } if (snapCount > 0) { blocks[block.Hash] = block; } } }
private void ProcessIncomingBlock(uint height) { logger.Info("Processing block #" + height); var block = neo_api.GetBlock(height); if (block == null) { throw new Exception($"API failure, could not fetch block #{height}"); } foreach (var tx in block.transactions) { if (tx.type != TransactionType.InvocationTransaction) { continue; } List <AVMInstruction> code; try { code = NeoTools.Disassemble(tx.script); } catch { continue; } for (int i = 1; i < code.Count; i++) { var op = code[i]; // opcode data must contain the script hash to the Phantasma contract, otherwise ignore it if (op.opcode == OpCode.APPCALL && op.data != null && op.data.Length == 20) { var scriptHash = new UInt160(op.data); if (scriptHash != contract_hash) { continue; } var prev = code[i - 1]; if (prev.data == null) { continue; } var method = Encoding.ASCII.GetString(prev.data); int index = i - 3; var argCount = 1 + ((byte)code[index].opcode - (byte)OpCode.PUSH1); var args = new List <byte[]>(); while (argCount > 0) { index--; args.Add(code[index].data); argCount--; } switch (method) { case "registerMailbox": { var address = new UInt160(args[0]); var name = Encoding.ASCII.GetString(args[1]); string result; if (addressMap.ContainsKey(address)) { result = "Address already has a box"; } else if (nameMap.ContainsKey(name)) { result = "Box name already exists"; } else if (!Mailbox.ValidateMailboxName(args[1])) { result = "Box name is invalid"; } else { var mailbox = new Mailbox(name, address); nameMap[name] = mailbox; addressMap[address] = mailbox; result = "OK"; } logger.Info($"{method} ({address.ToAddress()}, {name}) => {result}"); break; } } } } } }
static void Main(string[] pargs) { //var api = new LocalRPCNode(10332, "http://neoscan.io"); var api = new RemoteRPCNode(10332, "http://neoscan.io"); { Console.WriteLine("amount " + new BigInteger("00943577".HexToBytes())); Console.WriteLine("to " + new UInt160("fc3f33cb3e2d79f82fadef5f407ac1576d304bc1".HexToBytes()).ToAddress()); Console.WriteLine("from " + new UInt160("a30cadcc858aa4b89d9db098ef154c5e1ab74464".HexToBytes()).ToAddress()); return; } { var snap_data = File.ReadAllLines("souls_snap.csv"); var snap = Snapshot.Import(snap_data); var avm_script = File.ReadAllBytes(@"D:\code\Crypto\PhantasmaNeo\PhantasmaContract\bin\Debug\PhantasmaContract.avm"); var soul_token = api.GetToken("SOUL"); var lines = new List <string>(); uint ico_war_time = 1527465600; uint ico_start_time = 1527379200; Console.WriteLine("Block,Stage,Tx Hash,Address,Action,NEO sent,NEO refund"); snap.Execute(soul_token, avm_script, vm => { var storage = vm.GetStorage(soul_token); var block = vm.currentBlock; int stage = (block.Timestamp < ico_war_time) ? ((block.Timestamp < ico_start_time) ? 0 : 1) : 2; //var bytes = storage.Get("totalSupply"); //var n = new BigInteger(bytes); foreach (var tx in block.transactions) { UInt160 src = null; /*foreach (var input in tx.inputs) * { * var input_tx = snap.GetTransaction(input.prevHash); * if (input_tx == null) * { * input_tx = api.GetTransaction(input.prevHash); * } * var output = input_tx.outputs[input.prevIndex]; * src = output.scriptHash; * } * * if (src == null) * { * continue; * }*/ decimal neo_sent = 0; foreach (var output in tx.outputs) { if (output.scriptHash == soul_token.ScriptHash) { neo_sent += output.value; } } var src_address = src != null ? src.ToAddress(): "???"; if (tx.Hash.ToString() == "0xc39fb2304f721382a40142ed8af9d4470850f39fabeef9bb8bad892a6b63f4d6") { src_address += ""; } if (tx.type == TransactionType.ContractTransaction) { decimal refund = 0; foreach (var output in tx.outputs) { if (output.scriptHash == soul_token.ScriptHash) { refund += output.value; } } Console.WriteLine($"Block #{block.Height},{stage},{tx.Hash},{src_address},contract,{neo_sent},{refund}"); } else { var notifications = vm.GetNotifications(tx); if (notifications != null) { foreach (var entry in notifications) { decimal refund = 0; if (entry.Name == "refund") { var bytes = (byte[])entry.Args[1]; var n = new BigInteger(bytes); refund = (decimal)(n / 100000000); } Console.WriteLine($"Block #{block.Height},{stage},{entry.Hash},{src_address},{entry.Name},{neo_sent},{refund}"); } } } } }); return; } uint roundBlock = 2320640; uint startBlock = 2313827; uint endBlock = 2320681; { var snap = new Snapshot(api.GetToken("SOUL"), startBlock, endBlock); var export = snap.Export(); File.WriteAllLines("souls_snap.csv", export.ToArray()); return; } //startBlock = roundBlock; var soul_hash = LuxUtils.ReverseHex("ed07cffad18f1308db51920d99a2af60ac66a7b3").HexToBytes(); var soul_hash_int = new UInt160(soul_hash); var startT = Environment.TickCount; uint maxblock = 0; var blockCount = api.GetBlockHeight(); var soul_balances = new Dictionary <UInt160, BigInteger>(); var bought = new Dictionary <UInt160, decimal>(); BigInteger max_supply = 91136510; // total token amount BigInteger team_supply = 14500000; // team token amount BigInteger advisor_supply = 5500000; // advisor token amount BigInteger platform_supply = 15000000; // company token amount BigInteger presale_supply = 43503435; // presale token amount BigInteger total_supply = team_supply + advisor_supply + presale_supply + platform_supply; var whitelist = new HashSet <UInt160>(); var maybe = new HashSet <UInt160>(); var sure = new HashSet <UInt160>(); var expected = new Dictionary <UInt160, decimal>(); var txlist = new List <string>(); for (uint height = startBlock; height <= endBlock; height++) { var block = api.GetBlock(height); //Console.WriteLine(height + " " + block.Timestamp.ToString()); foreach (var tx in block.transactions) { if (tx.type == TransactionType.ContractTransaction) { foreach (var output in tx.outputs) { if (output.scriptHash == soul_hash_int) { /*foreach (var input in tx.inputs) * { * var input_tx = api.GetTransaction(input.prevHash); * var outp = input_tx.outputs[input.prevIndex]; * var sender = outp.scriptHash; * Console.WriteLine($"refund,{tx.Hash},{sender.ToAddress()},{output.value}"); * break; * }*/ } } continue; } if (tx.type != TransactionType.InvocationTransaction) { continue; } List <AVMInstruction> ops; try { ops = NeoTools.Disassemble(tx.script); } catch { continue; } if (tx.Hash.ToString() == "0xcf530159dc7fa7d0ea38ca210b479b04da20039b3b6639cf4c06bf528d415339") { tx.gas += 0; } for (int i = 0; i < ops.Count; i++) { var op = ops[i]; if (op.opcode == OpCode.APPCALL && op.data.SequenceEqual(soul_hash)) { var engine = new ExecutionEngine(null); engine.LoadScript(tx.script); engine.Execute(null); var operation = engine.EvaluationStack.Peek().GetString(); var args = ((IEnumerable <StackItem>)engine.EvaluationStack.Peek(1)).ToList(); var witnesses = new HashSet <UInt160>(); foreach (var input in tx.inputs) { var input_tx = api.GetTransaction(input.prevHash); witnesses.Add(input_tx.outputs[input.prevIndex].scriptHash); } switch (operation) { case "mintTokens": { decimal neo_amount = 0; foreach (var output in tx.outputs) { if (output.scriptHash == soul_hash_int) { neo_amount += output.value; } } var sender = witnesses.First(); var cur_bought = bought.ContainsKey(sender) ? bought[sender] : 0; decimal refund = 0; if (block.Height >= roundBlock) { maybe.Add(sender); expected[sender] = neo_amount * 273; } if (!whitelist.Contains(sender)) { refund = neo_amount; neo_amount = 0; } else if (cur_bought + neo_amount > 10) { var temp = neo_amount; neo_amount = 10 - cur_bought; refund = temp - neo_amount; } if (neo_amount > 0) { BigInteger souls = (int)neo_amount * 273; /*if (souls + total_supply > max_supply) * { * souls = max_supply - total_supply; * }*/ total_supply += souls * 2; if (soul_balances.ContainsKey(sender)) { soul_balances[sender] += new BigInteger((long)(souls * 100000000)); } else { soul_balances[sender] = new BigInteger((long)(souls * 100000000)); } Console.WriteLine(block.Height + "," + tx.Hash + ",mint," + soul_hash_int.ToAddress() + "," + sender.ToAddress() + "," + souls); cur_bought += neo_amount; bought[sender] = cur_bought; } else if (refund > 0) { Console.WriteLine(block.Height + "," + tx.Hash + ",refund," + soul_hash_int.ToAddress() + "," + sender.ToAddress() + "," + refund); } break; } case "whitelistAddFree": { foreach (var addr in args) { var hash = new UInt160(addr.GetByteArray()); whitelist.Add(hash); } break; } case "whitelistAddFilled": { foreach (var addr in args) { var hash = new UInt160(addr.GetByteArray()); whitelist.Add(hash); bought[hash] = 2730; } break; } case "whitelistAddCap": { decimal cap = 0; int index = 0; foreach (var addr in args) { if (index == 0) { var amount = addr.GetBigInteger(); cap = (decimal)(amount / 100000000); } else { var hash = new UInt160(addr.GetByteArray()); whitelist.Add(hash); bought[hash] = cap; } index++; } break; } case "chainSwap": { throw new Exception("Exploit found"); break; } case "deploy": { soul_balances[new UInt160("Abyd4BcStNksGLmfdHtyyPbS1xzhceDKLs".AddressToScriptHash())] = new BigInteger((long)6316538 * (long)100000000); soul_balances[new UInt160("ARWHJefSbhayC2gurKkpjMHm5ReaJZLLJ3".AddressToScriptHash())] = new BigInteger((long)43503435 * (long)100000000); soul_balances[new UInt160("AQFQmVQi9VReLhym1tF3UfPk4EG3VKbAwN".AddressToScriptHash())] = new BigInteger((long)15000000 * (long)100000000); break; } case "transfer": { if (args.Count == 3) { var from = new UInt160(args[0].GetByteArray()); if (!witnesses.Contains(from)) { //throw new Exception("Invalid"); } if (maybe.Contains(from)) { sure.Add(from); } var to = new UInt160(args[1].GetByteArray()); var value = args[2].GetBigInteger(); var from_addr = from.ToAddress(); var to_addr = to.ToAddress(); /*if (from == watch) * { * Console.WriteLine("WATCH " + tx.Hash); * } * if (to == watch) * { * Console.WriteLine("WATCH " + tx.Hash); * }*/ decimal amount = (long)value; int places = 8; while (places > 0) { amount *= 0.1m; places--; } Console.WriteLine(block.Height + "," + tx.Hash + ",transfer," + from.ToAddress() + "," + to.ToAddress() + "," + amount); } break; } } } } } } /*var lines = new List<string>(); * foreach (var entry in soul_balances) * { * var k = (long)entry.Value; * if (k == 0) * { * continue; * } * var val = (decimal)k / 100000000m; * lines.Add(entry.Key.ToAddress() + "," + val); * } * File.WriteAllLines("sale_soul.csv", lines.ToArray());*/ var token = api.GetToken("SOUL"); foreach (var entry in maybe) { var addr = entry.ToAddress(); var balance = token.BalanceOf(addr); if (balance >= expected[entry]) { sure.Add(entry); } } foreach (var entry in sure) { maybe.Remove(entry); Console.WriteLine(entry.ToAddress() + "," + expected[entry]); if (expected[entry] > 50 * 273) { throw new Exception("AAAAAAAAA"); } } foreach (var entry in maybe) { Console.WriteLine(entry.ToAddress() + ",0"); } decimal total = 0; foreach (var entry in sure) { total += expected[entry]; } Console.WriteLine("TOTAL " + total); var endT = Environment.TickCount; var delta = (endT - startT) / 1000; Console.WriteLine("Finished in " + delta + " seconds, loaded " + maxblock + " blocks"); Console.ReadLine(); return; /* Console.WriteLine(tkk.BalanceOf("AYxnCZePKhrijk2TQymYYUqm74nuwCftwq")); * //var token = api.GetToken("SOUL"); * //var keys = KeyPair.FromWIF("KxnjzXUvK9BLojMrWVJF7jjdbHs37aXvHyFog4rARGNrAQ7LFjLP"); * * var token = api.GetToken("OBT"); * var keys = KeyPair.FromWIF("L5YiR4AdUibLeFf48W3P5P36aBTWANcDu6oQNkvpaQrrHreg4RZC"); * * var balance = token.BalanceOf(keys); * Console.WriteLine(balance); * * var transfers = new Dictionary<string, decimal>(); * transfers["AHXWzaYCNYBYvhSypfi2XpAiWz2cCXrDJr"] = 16.7m; * transfers["AHxXMh9cPjE3cYrA9DhWNSBY2hC3a62PcH"] = 16.7m; * transfers["AHY7SidKpLuNj881Mc4Vjsj1Y4jBbX5EPS"] = 16.7m; * * var txx = token.Transfer(keys, transfers); * Console.WriteLine(txx.Hash);*/ /* * uint startBlock = 2298101; * uint endblock = 2313169; * * var soul_hash = LuxUtils.ReverseHex("4b4f63919b9ecfd2483f0c72ff46ed31b5bbb7a4").HexToBytes(); * var soul_hash_int = new UInt160(soul_hash); * * * var startT = Environment.TickCount; * * uint maxblock = 0; * * var blockCount = api.GetBlockHeight(); * * var soul_balances = new Dictionary<UInt160, BigInteger>(); * var bought = new Dictionary<UInt160, decimal>(); * * BigInteger max_supply = 91136510; // total token amount * BigInteger team_supply = 14500000; // team token amount * BigInteger advisor_supply = 5500000; // advisor token amount * BigInteger platform_supply = 15000000; // company token amount * BigInteger presale_supply = 43503435; // presale token amount * * BigInteger total_supply = team_supply + advisor_supply + presale_supply + platform_supply; * * var watch = new UInt160( "AQkiyWfwxMT31epRRxWXbR7wvZJH944jqh".AddressToScriptHash()); * * for (uint height = startBlock; height<=endblock; height++) * { * var block = api.GetBlock(height); * * //Console.WriteLine(height + " " + block.Timestamp.ToString()); * * foreach (var tx in block.transactions) * { * if (tx.type != TransactionType.InvocationTransaction) * { * continue; * } * * List<AVMInstruction> ops; * try * { * ops = NeoTools.Disassemble(tx.script); * } * catch * { * continue; * } * * if (tx.Hash.ToString()== "0xcf530159dc7fa7d0ea38ca210b479b04da20039b3b6639cf4c06bf528d415339") * { * tx.gas += 0; * } * * for (int i = 0; i < ops.Count; i++) * { * var op = ops[i]; * * if (op.opcode == OpCode.APPCALL && op.data.SequenceEqual(soul_hash)) * { * var engine = new ExecutionEngine(null); * engine.LoadScript(tx.script); * engine.Execute(null); * * var operation = engine.EvaluationStack.Peek().GetString(); * * var witnesses = new HashSet<UInt160>(); * foreach (var input in tx.inputs) * { * var input_tx = api.GetTransaction(input.prevHash); * witnesses.Add(input_tx.outputs[input.prevIndex].scriptHash); * } * * switch (operation) * { * case "mintTokens": * { * decimal neo_amount = 0; * * if (block.Timestamp.ToTimestamp() < 1526947200) * { * break; * } * * if (block.Height> 2298690) * { * break; * } * * foreach (var output in tx.outputs) * { * if (output.scriptHash == soul_hash_int) * { * neo_amount += output.value; * } * } * * var sender = witnesses.First(); * var cur_bought = bought.ContainsKey(sender) ? bought[sender] : 0; * * if (cur_bought + neo_amount > 10) * { * neo_amount = 10 - cur_bought; * } * * foreach (var wit in witnesses) * { * if (wit == watch) * { * Console.WriteLine("WATCH " + tx.Hash); * break; * } * } * * if (neo_amount > 0) * { * BigInteger souls = (int)neo_amount * 273; * //if (souls + total_supply > max_supply) * //{ * // souls = max_supply - total_supply; * //} * * total_supply += souls * 2; * * if (soul_balances.ContainsKey(sender)) * { * soul_balances[sender] += new BigInteger((long)(souls * 100000000)); * } * else * { * soul_balances[sender] = new BigInteger((long)(souls * 100000000)); * } * * Console.WriteLine(tx.Hash + ",mint," + soul_hash_int.ToAddress() + "," + sender.ToAddress() + "," + souls); * cur_bought += neo_amount; * bought[sender] = cur_bought; * } * * break; * } * * case "chainSwap": * { * throw new Exception("Exploit found"); * break; * } * * case "transfer": * { * var args = (Neo.Lux.VM.Types.Array)engine.EvaluationStack.Peek(1); * * if (args.Count == 3) * { * var from = new UInt160(args[0].GetByteArray()); * * if (!witnesses.Contains(from)) * { * //throw new Exception("Invalid"); * } * * var to = new UInt160(args[1].GetByteArray()); * var value = args[2].GetBigInteger(); * * var from_addr = from.ToAddress(); * var to_addr = to.ToAddress(); * * if (from == watch) * { * Console.WriteLine("WATCH " + tx.Hash); * } * if (to == watch) * { * Console.WriteLine("WATCH " + tx.Hash); * } * * if (from_addr == "AdkLubeJgL3PCKc1Xv6CEv9PrzB4c5AKNk") * { * value += 0; * } * * if (soul_balances.ContainsKey(from)) * { * var src_balance = soul_balances[from]; * * if (src_balance >= value) * { * src_balance -= value; * soul_balances[from] = src_balance; * * if (soul_balances.ContainsKey(to)) * { * soul_balances[to] += value; * } * else * { * soul_balances[to] = value; * } * } * } * else * { * throw new Exception("Invalid balance"); * } * * decimal amount = (long)value; * int places = 8; * while (places > 0) * { * amount *= 0.1m; * places--; * } * * Console.WriteLine(tx.Hash + ",transfer," + from.ToAddress() + "," + to.ToAddress() + "," + amount); * } * * break; * } * } * * } * * } * } * } * * var lines = new List<string>(); * foreach(var entry in soul_balances) * { * var k = (long)entry.Value; * if (k == 0) * { * continue; * } * var val = (decimal)k / 100000000m; * lines.Add(entry.Key.ToAddress() + "," + val); * } * File.WriteAllLines("soul_snapshop.csv", lines.ToArray()); * * var endT = Environment.TickCount; * var delta = (endT - startT) / 1000; * Console.WriteLine("Finished in " + delta + " seconds, loaded "+maxblock+" blocks"); * * Console.ReadLine(); */ }
public void Execute(NeoAPI api, UInt160 script_hash, Action <ListenerVM> visitor) { var balances = new Dictionary <UInt160, decimal>(); var vm = new ListenerVM(this); /*vm.AddScript(token_script); * * var debugger = new DebugClient(); * debugger.SendScript(token_script); */ throw new NotImplementedException(); IEnumerable <Block> sorted_blocks = blocks.Values.OrderBy(x => x.Date); foreach (var block in sorted_blocks) { vm.SetCurrentBlock(block); bool executed = false; foreach (var tx in block.transactions) { switch (tx.type) { case TransactionType.InvocationTransaction: { List <AVMInstruction> ops; try { ops = NeoTools.Disassemble(tx.script); } catch { continue; } for (int i = 0; i < ops.Count; i++) { var op = ops[i]; if (op.opcode == OpCode.APPCALL && op.data != null && op.data.Length == 20) { var otherScriptHash = new UInt160(op.data); if (otherScriptHash != script_hash) { continue; } var engine = new ExecutionEngine(tx, vm, vm); engine.LoadScript(tx.script); engine.Execute( x => { //debugger.Step(x); } ); executed = true; } } break; } } } if (executed) { visitor(vm); } } }
private bool ProcessIncomingBlock(uint height) { //Console.WriteLine($"Processing block {height}..."); var block = _api.GetBlock(height); if (block == null) { Console.WriteLine($"WARNING: could not fetch block #{height}"); return(false); } foreach (var tx in block.transactions) { //Console.WriteLine($"{height} Processing tx {tx.Hash}..."); //if (tx.type != TransactionType.InvocationTransaction) //{ // continue; //} List <AVMInstruction> txScript; try { txScript = NeoTools.Disassemble(tx.script); Console.WriteLine($"{height} Processing tx {tx.Hash} has {txScript.Count} instructions ({tx.script.Length} bytes. hash {tx.script.ToScriptHash()})"); } catch { continue; } var engine = new ExecutionEngine(tx, _listenerVM, _listenerVM); engine.LoadScript(tx.script); for (int i = 0; i < txScript.Count; i++) { AVMInstruction instruction = txScript[i]; Console.WriteLine($"Opcode {i}\t{instruction.opcode} ({(int)instruction.opcode}, {Helpers.ToHex(new byte[] { (byte)instruction.opcode })})\t{Helpers.ToHex(instruction.data)}\t{(instruction.data == null ? "(null)" : Encoding.ASCII.GetString(instruction.data))}"); if (instruction.opcode == OpCode.APPCALL && instruction.data != null && instruction.data.Length == 20) { var scriptHash = new UInt160(instruction.data); string scriptHashString = scriptHash.ToString(); Console.WriteLine($"scriptHashString: {scriptHashString}"); if (scriptHash != _contractScriptHash) { Console.WriteLine($"scriptHashString: {scriptHashString} != _contractScriptHash: {_contractScriptHash}: skipping"); continue; } var prevInstruction = txScript[i - 1]; if (prevInstruction.data == null) { Console.WriteLine($"scriptHashString: {scriptHashString}: no method - skipping"); continue; } _listenerVM.AddScript(_contractBytecode); var method = Encoding.ASCII.GetString(prevInstruction.data); int index = i - 3; int argCount = (byte)txScript[index].opcode - 0x50; // (byte)OpCode.PUSH0; var args = new List <byte[]>(); Console.WriteLine($"method: {method}: argCount {argCount}"); while (argCount > 0) { index--; if (txScript[index].data != null) { args.Add(txScript[index].data); Console.WriteLine($"arg: index {index} value {txScript[index].data.ToHexString()}"); } else if ((byte)txScript[index].opcode >= (byte)OpCode.PUSH1 && (byte)txScript[index].opcode <= (byte)OpCode.PUSH16) { int value = (byte)txScript[index].opcode - 0x50; Console.WriteLine($"arg: index {index} value {value}"); } argCount--; } engine.Execute(null /*x => * { * debugger.Step(x); * }*/ ); ProcessNotifications(height, tx); } } } //Console.WriteLine($"Processing block {height} success"); return(true); }