Example #1
0
 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;
     }
 }
Example #2
0
        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);
        }
Example #3
0
        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);
            }
        }
    }
Example #4
0
        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()));
            }
        }
Example #5
0
        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);
        }
Example #6
0
 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
             });
         }
     }
 }