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); }
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); }
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); }
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 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); } } } }
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); }