public VirtualChain(CronAPI api, KeyPair owner, ChainTime time = null) { Reset(); if (time == null) { time = new RealTime(); } this.Time = time; var scripthash = new UInt160(owner.signatureHash.ToArray()); var txs = new List <Transaction>(); foreach (var entry in _assetMap) { var assetID = entry.Key; var tx = new Transaction(); tx.outputs = new Transaction.Output[] { new Transaction.Output() { assetID = assetID, scriptHash = scripthash, value = 1000000000 } }; tx.inputs = new Transaction.Input[] { }; txs.Add(tx); } GenerateBlock(txs); }
public static uint FindBlock(CronAPI api, DateTime date) { uint min = 0; var max = api.GetBlockHeight(); var timestamp = date.ToTimestamp(); return(FindBlock(api, timestamp, min, max)); }
public void SyncWithNode(CronAPI api) { var max = api.GetBlockHeight(); var min = (uint)_blocks.Count; for (uint i = min; i <= max; i++) { var block = api.GetBlock(i); AddBlock(block); } }
public static Transaction MintTokens(NEP5 token, KeyPair buyer_key, string symbol, decimal amount) { var attachs = new List <Transaction.Output>(); attachs.Add(new Transaction.Output() { assetID = CronAPI.GetAssetID(symbol), scriptHash = token.ScriptHash, value = amount }); var response = token.api.CallContract(buyer_key, token.ScriptHash, "mintTokens", new object[] { }, symbol, attachs); return(response); }
public Transaction ClaimGas(KeyPair ownerKey) { var targetScriptHash = new UInt160(ownerKey.address.AddressToScriptHash()); decimal amount; var claimable = GetClaimable(targetScriptHash, out amount); var references = new List <Transaction.Input>(); foreach (var entry in claimable) { references.Add(new Transaction.Input() { prevHash = entry.hash, prevIndex = entry.index }); } if (amount <= 0) { throw new ArgumentException("No GAS to claim at this address"); } List <Transaction.Input> inputs; List <Transaction.Output> outputs; GenerateInputsOutputs(ownerKey, "CRON", null, out inputs, out outputs); outputs.Add( new Transaction.Output() { scriptHash = targetScriptHash, assetID = CronAPI.GetAssetID("CRON"), value = amount }); Transaction tx = new Transaction() { type = TransactionType.ClaimTransaction, version = 0, script = null, gas = -1, claimReferences = references.ToArray(), inputs = inputs.ToArray(), outputs = outputs.ToArray(), }; tx.Sign(ownerKey); var ok = SendTransaction(tx); return(ok ? tx : null); }
private void MergeTransaction(CronAPI api, Transaction tx) { transactions[tx.Hash] = tx; foreach (var input in tx.inputs) { if (!transactions.ContainsKey(input.prevHash)) { var other = api.GetTransaction(input.prevHash); transactions[other.Hash] = other; external_txs.Add(other.Hash); } } }
protected override void Reset() { base.Reset(); foreach (var entry in CronAPI.Assets) { var symbol = entry.Key; var assetID = CronAPI.GetAssetID(symbol); _assetMap[assetID] = new Asset() { hash = new UInt256(assetID), name = symbol }; } }
// transfer to multiple addresses public Transaction Transfer(KeyPair from_key, Dictionary <byte[], decimal> transfers) { if (transfers.Count > max_transfer_count) { throw new ArgumentException("Max transfers per call = " + max_transfer_count); } var scripts = new List <byte[]>(); var sender_address_hash = from_key.address.GetScriptHashFromAddress(); int index = 0; foreach (var entry in transfers) { if (entry.Value <= 0) { var addr = new UInt160(entry.Key).ToAddress(); throw new ArgumentException($"Invalid amount {entry.Value} for address {addr}"); } BigInteger amount = ConvertToBigInt(entry.Value); var isLast = index == transfers.Count - 1; var args = new object[] { sender_address_hash, entry.Key, amount }; var bytes = CronAPI.GenerateScript(ScriptHash, new object[] { "transfer", args }, isLast); scripts.Add(bytes); index++; } var final_size = scripts.Sum(x => x.Length); byte[] final_script = new byte[final_size]; using (var stream = new MemoryStream(final_script)) { foreach (byte[] bytes in scripts) { stream.Write(bytes, 0, bytes.Length); } } var response = api.CallContract(from_key, ScriptHash, final_script); return(response); }
private static uint FindBlock(CronAPI api, uint timestamp, uint min, uint max) { var mid = (1 + max - min) / 2; do { var block = api.GetBlock(mid); var blockTime = block.Date.ToTimestamp(); if (blockTime == timestamp) { return(block.Height); } else if (blockTime < timestamp) { var next = api.GetBlock(mid + 1); var nextTime = next.Date.ToTimestamp(); if (nextTime == timestamp) { return(next.Height); } else if (nextTime > timestamp) { return(block.Height); } else { return(FindBlock(api, timestamp, mid + 1, max)); } } else { return(FindBlock(api, timestamp, min, mid - 1)); } } while (true); }
// claim from contract, without having private key public Transaction ClaimGas(KeyPair ownerKey, UInt160 fromScripthash, byte[] verificationScript) { var check = verificationScript.ToScriptHash(); if (check != fromScripthash) { throw new ArgumentException("Invalid verification script"); } decimal amount; var claimable = GetClaimable(fromScripthash, out amount); var references = new List <Transaction.Input>(); foreach (var entry in claimable) { references.Add(new Transaction.Input() { prevHash = entry.hash, prevIndex = entry.index }); } if (amount <= 0) { throw new ArgumentException("No GAS to claim at this address"); } List <Transaction.Input> inputs; List <Transaction.Output> outputs; GenerateInputsOutputs(ownerKey, "CRON", null, out inputs, out outputs); outputs.Add( new Transaction.Output() { scriptHash = fromScripthash, assetID = CronAPI.GetAssetID("CRON"), value = amount }); Transaction tx = new Transaction() { type = TransactionType.ClaimTransaction, version = 0, script = null, gas = -1, claimReferences = references.ToArray(), inputs = inputs.ToArray(), outputs = outputs.ToArray(), }; var witness = new Witness { invocationScript = ("0014" + ownerKey.address.AddressToScriptHash().ByteToHex()).HexToBytes(), verificationScript = verificationScript }; tx.Sign(ownerKey, new Witness[] { witness }); var ok = SendTransaction(tx); return(ok ? tx : null); }
public BlockIterator(CronAPI api) { this.currentBlock = api.GetBlockHeight(); this.currentTransaction = 0; }
public void Execute(CronAPI 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 = CronTools.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); } } }
public NEP5(CronAPI api, string contractHash) : this(api, CronAPI.GetScriptHashFromString(contractHash)) { }
public Snapshot(UInt160 scriptHash, CronAPI api, uint startBlock, uint endBlock = 0) { 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 == scriptHash) { MergeTransaction(api, tx); snapCount++; break; } } break; } case TransactionType.InvocationTransaction: { List <AVMInstruction> ops; try { ops = CronTools.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 == scriptHash) { MergeTransaction(api, tx); snapCount++; break; } } } break; } } } if (snapCount > 0) { blocks[block.Hash] = block; } } }
public NEP5(CronAPI api, string contractHash, string name, BigInteger decimals) : this(api, contractHash) { this._decimals = decimals; this._name = name; }
public NEP5(CronAPI api, UInt160 contractHash) { this.api = api; this.ScriptHash = contractHash; }
public NEP5(CronAPI api, byte[] contractHash) : this(api, new UInt160(contractHash)) { }