public AssetDescriptor(UIntBase asset_id, UInt256 ChainHash) { if (asset_id is UInt160 asset_id_160) { byte[] script; using (ScriptBuilder sb = new ScriptBuilder()) { sb.EmitAppCall(asset_id_160, "decimals"); sb.EmitAppCall(asset_id_160, "name"); script = sb.ToArray(); } ApplicationEngine engine = ApplicationEngine.Run(script, ChainHash); if (engine.State.HasFlag(VMState.FAULT)) { throw new ArgumentException(); } this.AssetId = asset_id; this.AssetName = engine.EvaluationStack.Pop().GetString(); this.Decimals = (byte)engine.EvaluationStack.Pop().GetBigInteger(); } else { AssetState state = BlockchainBase.GetBlockchain(ChainHash).GetAssetState((UInt256)asset_id); this.AssetId = state.AssetId; this.AssetName = state.GetName(); this.Decimals = state.Precision; } }
public IEnumerable <Coin> GetUnclaimedCoins() { IEnumerable <UInt160> accounts = GetAccounts().Where(p => !p.Lock && !p.WatchOnly).Select(p => p.ScriptHash); IEnumerable <Coin> coins = GetCoins(accounts); coins = coins.Where(p => p.Output.AssetId.Equals(BlockchainBase.GetStaticAttr().GoverningToken.Hash)); coins = coins.Where(p => p.State.HasFlag(CoinState.Confirmed) && p.State.HasFlag(CoinState.Spent)); coins = coins.Where(p => !p.State.HasFlag(CoinState.Claimed) && !p.State.HasFlag(CoinState.Frozen)); return(coins); }
public static ApplicationEngine Run(byte[] script, UInt256 ChainHash, IScriptContainer container = null, Block persisting_block = null) { BlockchainBase Chain = BlockchainBase.GetBlockchain(ChainHash); if (persisting_block == null) { persisting_block = new Block(ChainHash) { Version = 0, PrevHash = Chain.CurrentBlockHash, MerkleRoot = new UInt256(), Timestamp = Chain.GetHeader(Chain.Height).Timestamp + Chain.SecondsPerBlock, Index = Chain.Height + 1, ConsensusData = 0, NextConsensus = Chain.GetHeader(Chain.Height).NextConsensus, Script = new Witness { InvocationScript = new byte[0], VerificationScript = new byte[0] }, Transactions = new Transaction[0] } } ; DataCache <UInt160, AccountState> accounts = Chain.GetStates <UInt160, AccountState>(); DataCache <UInt256, AssetState> assets = Chain.GetStates <UInt256, AssetState>(); DataCache <UInt160, ContractState> contracts = Chain.GetStates <UInt160, ContractState>(); DataCache <StorageKey, StorageItem> storages = Chain.GetStates <StorageKey, StorageItem>(); CachedScriptTable script_table = new CachedScriptTable(contracts); using (StateMachine service = new StateMachine(persisting_block, accounts, assets, contracts, storages)) { ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, container, script_table, service, Fixed8.Zero, true); engine.LoadScript(script, false); engine.Execute(); return(engine); } } }
private void OnGetBlocksMessageReceived(GetBlocksPayload payload) { if (!localNode.ServiceEnabled) { return; } BlockchainBase Chain = BlockchainBase.GetBlockchain(payload.ChainHash); if (Chain == null) { return; } UInt256 hash = payload.HashStart.Select(p => Chain.GetHeader(p)).Where(p => p != null).OrderBy(p => p.Index).Select(p => p.Hash).FirstOrDefault(); if (hash == null || hash == payload.HashStop) { return; } List <UInt256> hashes = new List <UInt256>(); do { hash = Chain.GetNextBlockHash(hash); if (hash == null) { break; } hashes.Add(hash); } while (hash != payload.HashStop && hashes.Count < 500); if (hashes.Count > 0) { EnqueueMessage("inv", InvPayload.Create(InventoryType.Block, hashes.ToArray())); } }
public T MakeTransaction <T>(T tx, UInt160 from = null, UInt160 change_address = null, Fixed8 fee = default(Fixed8)) where T : Transaction { if (tx.Outputs == null) { tx.Outputs = new TransactionOutput[0]; } if (tx.Attributes == null) { tx.Attributes = new TransactionAttribute[0]; } fee += tx.SystemFee; var pay_total = (typeof(T) == typeof(IssueTransaction) ? new TransactionOutput[0] : tx.Outputs).GroupBy(p => p.AssetId, (k, g) => new { AssetId = k, Value = g.Sum(p => p.Value) }).ToDictionary(p => p.AssetId); if (fee > Fixed8.Zero) { if (pay_total.ContainsKey(BlockchainBase.GetStaticAttr().UtilityToken.Hash)) { pay_total[BlockchainBase.GetStaticAttr().UtilityToken.Hash] = new { AssetId = BlockchainBase.GetStaticAttr().UtilityToken.Hash, Value = pay_total[BlockchainBase.GetStaticAttr().UtilityToken.Hash].Value + fee }; } else { pay_total.Add(BlockchainBase.GetStaticAttr().UtilityToken.Hash, new { AssetId = BlockchainBase.GetStaticAttr().UtilityToken.Hash, Value = fee }); } } var pay_coins = pay_total.Select(p => new { AssetId = p.Key, Unspents = from == null ? FindUnspentCoins(p.Key, p.Value.Value) : FindUnspentCoins(p.Key, p.Value.Value, from) }).ToDictionary(p => p.AssetId); if (pay_coins.Any(p => p.Value.Unspents == null)) { return(null); } var input_sum = pay_coins.Values.ToDictionary(p => p.AssetId, p => new { p.AssetId, Value = p.Unspents.Sum(q => q.Output.Value) }); if (change_address == null) { change_address = GetChangeAddress(); } List <TransactionOutput> outputs_new = new List <TransactionOutput>(tx.Outputs); foreach (UInt256 asset_id in input_sum.Keys) { if (input_sum[asset_id].Value > pay_total[asset_id].Value) { outputs_new.Add(new TransactionOutput { AssetId = asset_id, Value = input_sum[asset_id].Value - pay_total[asset_id].Value, ScriptHash = change_address }); } } tx.Inputs = pay_coins.Values.SelectMany(p => p.Unspents).Select(p => p.Reference).ToArray(); tx.Outputs = outputs_new.ToArray(); return(tx); }
private static void ProcessBlock(Block block, HashSet <UInt160> accounts, WriteBatch batch) { foreach (Transaction tx in block.Transactions) { HashSet <UInt160> accounts_changed = new HashSet <UInt160>(); for (ushort index = 0; index < tx.Outputs.Length; index++) { TransactionOutput output = tx.Outputs[index]; if (accounts_tracked.ContainsKey(output.ScriptHash)) { CoinReference reference = new CoinReference { PrevHash = tx.Hash, PrevIndex = index }; if (coins_tracked.TryGetValue(reference, out Coin coin)) { coin.State |= CoinState.Confirmed; } else { accounts_tracked[output.ScriptHash].Add(reference); coins_tracked.Add(reference, coin = new Coin { Reference = reference, Output = output, State = CoinState.Confirmed }); } batch.Put(SliceBuilder.Begin(DataEntryPrefix.ST_Coin).Add(reference), SliceBuilder.Begin().Add(output).Add((byte)coin.State)); accounts_changed.Add(output.ScriptHash); } } foreach (CoinReference input in tx.Inputs) { if (coins_tracked.TryGetValue(input, out Coin coin)) { if (coin.Output.AssetId.Equals(BlockchainBase.GetStaticAttr().GoverningToken.Hash)) { coin.State |= CoinState.Spent | CoinState.Confirmed; batch.Put(SliceBuilder.Begin(DataEntryPrefix.ST_Coin).Add(input), SliceBuilder.Begin().Add(coin.Output).Add((byte)coin.State)); } else { accounts_tracked[coin.Output.ScriptHash].Remove(input); coins_tracked.Remove(input); batch.Delete(DataEntryPrefix.ST_Coin, input); } accounts_changed.Add(coin.Output.ScriptHash); } } if (tx is ClaimTransaction ctx) { foreach (CoinReference claim in ctx.Claims) { if (coins_tracked.TryGetValue(claim, out Coin coin)) { accounts_tracked[coin.Output.ScriptHash].Remove(claim); coins_tracked.Remove(claim); batch.Delete(DataEntryPrefix.ST_Coin, claim); accounts_changed.Add(coin.Output.ScriptHash); } } } if (accounts_changed.Count > 0) { foreach (UInt160 account in accounts_changed) { batch.Put(SliceBuilder.Begin(DataEntryPrefix.ST_Transaction).Add(account).Add(tx.Hash), false); } BalanceChanged?.Invoke(null, new BalanceEventArgs { Transaction = tx, RelatedAccounts = accounts_changed.ToArray(), Height = block.Index, Time = block.Timestamp }); } } }