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); } } } } }
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); }
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; } } }
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 }); } } } }
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); } }
public OrderedBalanceChange() { _SpentIndices = new List <uint>(); _SpentOutpoints = new List <OutPoint>(); _ReceivedCoins = new CoinCollection(); }
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); }