Пример #1
0
 private void UpdateToColoredCoins(CoinCollection collection, bool input)
 {
     if (collection == null)
     {
         return;
     }
     for (int i = 0; i < collection.Count; i++)
     {
         var coin = collection[i] as Coin;
         if (coin != null)
         {
             if (input)
             {
                 var txinIndex = SpentIndices[i];
                 var asset     = ColoredTransaction
                                 .Inputs
                                 .Where(_ => _.Index == (uint)txinIndex)
                                 .Select(_ => _.Asset)
                                 .FirstOrDefault();
                 if (asset != null)
                 {
                     collection[i] = coin.ToColoredCoin(asset);
                 }
             }
             else
             {
                 var asset = ColoredTransaction.GetColoredEntry(coin.Outpoint.N);
                 if (asset != null)
                 {
                     collection[i] = coin.ToColoredCoin(asset.Asset);
                 }
             }
         }
     }
 }
        public async Task <bool> EnsureSpentCoinsLoadedAsync(ITransactionRepository transactions)
        {
            if (SpentCoins != null)
            {
                return(true);
            }
            CoinCollection result = new CoinCollection();

            for (int i = 0; i < SpentOutpoints.Count; i++)
            {
                var outpoint = SpentOutpoints[i];
                if (outpoint.IsNull)
                {
                    continue;
                }
                var prev = await transactions.GetAsync(outpoint.Hash).ConfigureAwait(false);

                if (prev == null)
                {
                    return(false);
                }
                result.Add(new Coin(outpoint, prev.Outputs[SpentOutpoints[i].N]));
            }
            SpentCoins = result;
            UpdateToScriptCoins();
            return(true);
        }
Пример #3
0
        private static CoinCollection SelectSpentCoins(IEnumerable <OrderedBalanceChange> entries, bool spent)
        {
            CoinCollection result = new CoinCollection();
            Dictionary <OutPoint, ICoin> spentCoins    = new Dictionary <OutPoint, ICoin>();
            Dictionary <OutPoint, ICoin> receivedCoins = new Dictionary <OutPoint, ICoin>();

            foreach (var entry in entries)
            {
                if (entry.SpentCoins != null)
                {
                    foreach (var c in entry.SpentCoins)
                    {
                        spentCoins.AddOrReplace(c.Outpoint, c);
                    }
                }
                foreach (var c in entry.ReceivedCoins)
                {
                    receivedCoins.AddOrReplace(c.Outpoint, c);
                }
            }
            if (spent)
            {
                result.AddRange(spentCoins.Values.Select(s => s));
            }
            else
            {
                result.AddRange(receivedCoins.Where(r => !spentCoins.ContainsKey(r.Key)).Select(kv => kv.Value));
            }
            return(result);
        }
Пример #4
0
        public async Task <bool> EnsurePreviousLoadedAsync(OrderedBalanceChange change)
        {
            if (!NeedLoading(change))
            {
                return(true);
            }
            var transactions =
                await GetTransactionsAsync(false, ColoredBalance, change.SpentOutpoints.Select(s => s.Hash).ToArray()).ConfigureAwait(false);

            CoinCollection result = new CoinCollection();

            for (int i = 0; i < transactions.Length; i++)
            {
                var outpoint = change.SpentOutpoints[i];
                if (outpoint.IsNull)
                {
                    continue;
                }
                var prev = transactions[i];
                if (prev == null)
                {
                    return(false);
                }
                if (ColoredBalance && prev.ColoredTransaction == null)
                {
                    return(false);
                }
                result.Add(new Coin(outpoint, prev.Transaction.Outputs[change.SpentOutpoints[i].N]));
            }
            change.SpentCoins = result;


            if (ColoredBalance && change.ColoredBalanceChangeEntry == null)
            {
                var thisTransaction = await GetTransactionAsync(false, ColoredBalance, change.TransactionId).ConfigureAwait(false);

                if (thisTransaction.ColoredTransaction == null)
                {
                    return(false);
                }
                change.ColoredBalanceChangeEntry = new ColoredBalanceChangeEntry(change, thisTransaction.ColoredTransaction);
            }

            var entity     = change.ToEntity();
            var spentCoins = Helper.GetEntityProperty(entity, "b");
            var coloredTx  = ColoredBalance ? entity.Properties["g"].BinaryValue : null;

            entity.Properties.Clear();
            if (coloredTx != null)
            {
                entity.Properties.Add("g", new EntityProperty(coloredTx));
            }
            Helper.SetEntityProperty(entity, "b", spentCoins);
            Configuration.GetBalanceTable().Execute(TableOperation.Merge(entity));
            change.AddRedeemInfo();
            return(true);
        }
Пример #5
0
 private void UpdateToUncoloredCoins(CoinCollection collection)
 {
     if (collection == null)
     {
         return;
     }
     for (int i = 0; i < collection.Count; i++)
     {
         var coin = collection[i] as ColoredCoin;
         if (coin != null)
         {
             collection[i] = coin.Bearer;
         }
     }
 }
Пример #6
0
        internal void Merge(OrderedBalanceChange other, WalletRule walletRule)
        {
            if (other.ReceivedCoins.Count != 0)
            {
                ReceivedCoins.AddRange(other.ReceivedCoins);
                ReceivedCoins = new CoinCollection(ReceivedCoins.Distinct <ICoin, OutPoint>(c => c.Outpoint));
                if (walletRule != null)
                {
                    foreach (var c in other.ReceivedCoins)
                    {
                        this.MatchedRules.Add(new MatchedRule()
                        {
                            Index     = c.Outpoint.N,
                            Rule      = walletRule,
                            MatchType = MatchLocation.Output
                        });
                    }
                }
            }

            if (other.SpentIndices.Count != 0)
            {
                SpentIndices.AddRange(other.SpentIndices);
                SpentIndices = SpentIndices.Distinct().ToList();

                SpentOutpoints.AddRange(other.SpentOutpoints);
                SpentOutpoints = SpentOutpoints.Distinct().ToList();

                //Remove cached value, no longer correct
                UpdateToUncoloredCoins();
                SpentCoins = null;

                if (walletRule != null)
                {
                    foreach (var c in other.SpentIndices)
                    {
                        this.MatchedRules.Add(new MatchedRule()
                        {
                            Index     = c,
                            Rule      = walletRule,
                            MatchType = MatchLocation.Input
                        });
                    }
                }
            }
        }
Пример #7
0
 internal void AddRedeemInfo()
 {
     foreach (var match in MatchedRules)
     {
         var scriptRule = match.Rule as ScriptRule;
         if (scriptRule != null && scriptRule.RedeemScript != null)
         {
             CoinCollection collection = match.MatchType == MatchLocation.Input ? SpentCoins : ReceivedCoins;
             if (collection != null)
             {
                 var outpoint = new OutPoint(TransactionId, match.Index);
                 var coin     = collection[outpoint];
                 collection[outpoint] = new ScriptCoin(coin.Outpoint, coin.TxOut, scriptRule.RedeemScript);
             }
         }
     }
 }
Пример #8
0
        internal OrderedBalanceChange(DynamicTableEntity entity)
        {
            var splitted = entity.RowKey.Split(new string[] { "-" }, StringSplitOptions.RemoveEmptyEntries);

            Height    = Helper.StringToHeight(splitted[1]);
            BalanceId = BalanceId.Parse(splitted[0]);

            var locator     = BalanceLocator.Parse(string.Join("-", splitted.Skip(1).ToArray()), true);
            var confLocator = locator as ConfirmedBalanceLocator;

            if (confLocator != null)
            {
                Height        = confLocator.Height;
                TransactionId = confLocator.TransactionId;
                BlockId       = confLocator.BlockHash;
            }

            var unconfLocator = locator as UnconfirmedBalanceLocator;

            if (unconfLocator != null)
            {
                TransactionId = unconfLocator.TransactionId;
            }

            SeenUtc = entity.Properties["s"].DateTime.Value;

            _SpentOutpoints = Helper.DeserializeList <OutPoint>(Helper.GetEntityProperty(entity, "a"));

            if (entity.Properties.ContainsKey("b0"))
            {
                _SpentCoins = new CoinCollection(Helper.DeserializeList <Spendable>(Helper.GetEntityProperty(entity, "b")).Select(s => new Coin()
                {
                    Outpoint = s.OutPoint,
                    TxOut    = s.TxOut
                }).ToList());
            }
            else if (_SpentOutpoints.Count == 0)
            {
                _SpentCoins = new CoinCollection();
            }

            _SpentIndices = Helper.DeserializeList <IntCompactVarInt>(Helper.GetEntityProperty(entity, "ss")).Select(i => (uint)i.ToLong()).ToList();

            var receivedIndices = Helper.DeserializeList <IntCompactVarInt>(Helper.GetEntityProperty(entity, "c")).Select(i => (uint)i.ToLong()).ToList();
            var receivedTxOuts  = Helper.DeserializeList <TxOut>(Helper.GetEntityProperty(entity, "d"));

            _ReceivedCoins = new CoinCollection();
            for (int i = 0; i < receivedIndices.Count; i++)
            {
                _ReceivedCoins.Add(new Coin()
                {
                    Outpoint = new OutPoint(TransactionId, receivedIndices[i]),
                    TxOut    = receivedTxOuts[i]
                });
            }

            var flags = entity.Properties["e"].StringValue;

            HasOpReturn = flags[0] == 'o';
            IsCoinbase  = flags[1] == 'o';

            _MatchedRules = Helper.DeserializeObject <List <MatchedRule> >(entity.Properties["f"].StringValue).ToList();

            if (entity.Properties.ContainsKey("g"))
            {
                var ctx = new ColoredTransaction();
                ctx.FromBytes(entity.Properties["g"].BinaryValue);
                ColoredTransaction = ctx;
            }

            if (entity.Properties.ContainsKey("h"))
            {
                _ScriptPubKey = new Script(entity.Properties["h"].BinaryValue);
            }

            var data = Helper.GetEntityProperty(entity, "cu");

            if (data != null)
            {
                CustomData = Encoding.UTF8.GetString(data);
            }
        }
Пример #9
0
 public OrderedBalanceChange()
 {
     _SpentIndices   = new List <uint>();
     _SpentOutpoints = new List <OutPoint>();
     _ReceivedCoins  = new CoinCollection();
 }
Пример #10
0
        public async Task <bool> EnsureSpentCoinsLoadedAsync(ITransactionRepository transactions)
        {
            if (SpentCoins != null)
            {
                return(true);
            }

            bool           cleanSpent = false;
            CoinCollection result     = new CoinCollection();

            for (int i = 0; i < SpentOutpoints.Count; i++)
            {
                var outpoint = SpentOutpoints[i];
                if (outpoint.IsNull)
                {
                    continue;
                }
                var prev = await transactions.GetAsync(outpoint.Hash).ConfigureAwait(false);

                if (prev == null)
                {
                    return(false);
                }

                var coin = new Coin(outpoint, prev.Outputs[SpentOutpoints[i].N]);
                if (coin.ScriptPubKey != GetScriptPubkey(i))
                {
                    cleanSpent        = true;
                    SpentOutpoints[i] = null;
                }
                else
                {
                    result.Add(coin);
                }
            }

            if (cleanSpent)
            {
                List <uint>        spentIndices   = new List <uint>();
                List <OutPoint>    spentOutpoints = new List <OutPoint>();
                List <MatchedRule> matchedRules   = new List <MatchedRule>();
                for (int i = 0; i < SpentOutpoints.Count; i++)
                {
                    if (SpentOutpoints[i] != null)
                    {
                        spentIndices.Add(SpentIndices[i]);
                        spentOutpoints.Add(SpentOutpoints[i]);
                        if (MatchedRules != null && MatchedRules.Count != 0)
                        {
                            matchedRules.Add(MatchedRules[i]);
                        }
                    }
                }
                SpentIndices   = spentIndices;
                SpentOutpoints = spentOutpoints;
                MatchedRules   = matchedRules;
            }

            SpentCoins = result;
            UpdateToScriptCoins();
            return(true);
        }