public static async Task <ColoredTransaction> GetColoredTransactionAsync(this Transaction tx, IColoredTransactionRepository repo) { try { return(await ColoredTransaction.FetchColorsAsync(tx, repo).ConfigureAwait(false)); } catch (TransactionNotFoundException) { return(null); } }
public Task PutAsync(uint256 txId, ColoredTransaction tx) { if (WriteThrough) { using (_lock.LockWrite()) { if (!_ColoredTransactions.ContainsKey(txId)) { _ColoredTransactions.AddOrReplace(txId, tx); EvictIfNecessary(txId); } else { _ColoredTransactions[txId] = tx; } } } return(_Inner.PutAsync(txId, tx)); }
public async Task <ColoredTransaction> GetAsync(uint256 txId) { ColoredTransaction result = null; bool found; using (_lock.LockRead()) { found = _ColoredTransactions.TryGetValue(txId, out result); } if (!found) { result = await _Inner.GetAsync(txId).ConfigureAwait(false); if (ReadThrough) { using (_lock.LockWrite()) { _ColoredTransactions.AddOrReplace(txId, result); EvictIfNecessary(txId); } } } return(result); }
public Task PutAsync(uint256 txId, ColoredTransaction tx) { return(Task.FromResult <bool>(true)); }
public async Task <ColoredTransaction> GetAsync(uint256 txId) { try { ColoredTransaction result = new ColoredTransaction(); String url = _network == Network.Main ? String.Format("https://api.coinprism.com/v1/transactions/{0}", txId) : String.Format("https://testnet.api.coinprism.com/v1/transactions/{0}", txId); HttpWebRequest req = HttpWebRequest.CreateHttp(url); req.Method = "GET"; #if !NOCUSTOMSSLVALIDATION if (_network == Network.TestNet) { req.ServerCertificateValidationCallback += (a, b, c, d) => true; } #endif using (var response = await req.GetResponseAsync().ConfigureAwait(false)) { var writer = new StreamReader(response.GetResponseStream()); var str = await writer.ReadToEndAsync().ConfigureAwait(false); var json = JObject.Parse(str); var inputs = json["inputs"] as JArray; if (inputs != null) { for (int i = 0; i < inputs.Count; i++) { if (inputs[i]["asset_id"].Value <string>() == null) { continue; } var entry = new ColoredEntry(); entry.Index = (uint)i; entry.Asset = new AssetMoney( new BitcoinAssetId(inputs[i]["asset_id"].ToString(), null).AssetId, inputs[i]["asset_quantity"].Value <ulong>()); result.Inputs.Add(entry); } } var outputs = json["outputs"] as JArray; if (outputs != null) { bool issuance = true; for (int i = 0; i < outputs.Count; i++) { var marker = ColorMarker.TryParse(new Script(Encoders.Hex.DecodeData(outputs[i]["script"].ToString()))); if (marker != null) { issuance = false; result.Marker = marker; continue; } if (outputs[i]["asset_id"].Value <string>() == null) { continue; } ColoredEntry entry = new ColoredEntry(); entry.Index = (uint)i; entry.Asset = new AssetMoney( new BitcoinAssetId(outputs[i]["asset_id"].ToString(), null).AssetId, outputs[i]["asset_quantity"].Value <ulong>() ); if (issuance) { result.Issuances.Add(entry); } else { result.Transfers.Add(entry); } } } return(result); } } catch (WebException ex) { try { var error = JObject.Parse(new StreamReader(ex.Response.GetResponseStream()).ReadToEnd()); if (error["ErrorCode"].ToString() == "InvalidTransactionHash") { return(null); } throw new CoinprismException(error["ErrorCode"].ToString()); } catch (CoinprismException) { throw; } catch { } throw; } }
public Task PutAsync(uint256 txId, ColoredTransaction tx) { return(Task.FromResult(false)); }
public static async Task <ColoredTransaction> FetchColorsAsync(uint256 txId, Transaction tx, IColoredTransactionRepository repo) { if (repo == null) { throw new ArgumentNullException("repo"); } if (txId == null) { if (tx == null) { throw new ArgumentException("txId or tx should be different of null"); } txId = tx.GetHash(); } //The following code is to prevent recursion of FetchColors that would fire a StackOverflow if the origin of traded asset were deep in the transaction dependency tree var colored = await repo.GetAsync(txId).ConfigureAwait(false); if (colored != null) { return(colored); } Stack <ColoredFrame> frames = new Stack <ColoredFrame>(); Stack <ColoredTransaction> coloreds = new Stack <ColoredTransaction>(); frames.Push(new ColoredFrame() { TransactionId = txId, Transaction = tx }); while (frames.Count != 0) { var frame = frames.Pop(); colored = frame.PreviousTransactions != null ? null : await repo.GetAsync(frame.TransactionId).ConfigureAwait(false); //Already known if (colored != null) { coloreds.Push(colored); continue; } frame.Transaction = frame.Transaction ?? await repo.Transactions.GetAsync(frame.TransactionId).ConfigureAwait(false); if (frame.Transaction == null) { throw new TransactionNotFoundException("Transaction " + frame.TransactionId + " not found in transaction repository", frame.TransactionId); } if (frame.PreviousTransactions == null) { if (frame.Transaction.IsCoinBase || (!frame.Transaction.HasValidColoredMarker() && frame.TransactionId != txId)) //We care about destroyed asset, if this is the requested transaction { coloreds.Push(new ColoredTransaction()); continue; } frame.PreviousTransactions = new ColoredTransaction[frame.Transaction.Inputs.Count]; await BulkLoadIfCached(frame.Transaction, repo).ConfigureAwait(false); frames.Push(frame); for (int i = 0; i < frame.Transaction.Inputs.Count; i++) { frames.Push(new ColoredFrame() { TransactionId = frame.Transaction.Inputs[i].PrevOut.Hash }); } frame.Transaction = frame.TransactionId == txId ? frame.Transaction : null; //Do not waste memory, will refetch later continue; } else { for (int i = 0; i < frame.Transaction.Inputs.Count; i++) { frame.PreviousTransactions[i] = coloreds.Pop(); } } Script issuanceScriptPubkey = null; if (HasIssuance(frame.Transaction)) { var txIn = frame.Transaction.Inputs[0]; var previous = await repo.Transactions.GetAsync(txIn.PrevOut.Hash).ConfigureAwait(false); if (previous == null) { throw new TransactionNotFoundException("An open asset transaction is issuing assets, but it needs a parent transaction in the TransactionRepository to know the address of the issued asset (missing : " + txIn.PrevOut.Hash + ")", txIn.PrevOut.Hash); } if (txIn.PrevOut.N < previous.Outputs.Count) { issuanceScriptPubkey = previous.Outputs[txIn.PrevOut.N].ScriptPubKey; } } List <ColoredCoin> spentCoins = new List <ColoredCoin>(); for (int i = 0; i < frame.Transaction.Inputs.Count; i++) { var txIn = frame.Transaction.Inputs[i]; var entry = frame.PreviousTransactions[i].GetColoredEntry(txIn.PrevOut.N); if (entry != null) { spentCoins.Add(new ColoredCoin(entry.Asset, new Coin(txIn.PrevOut, new TxOut()))); } } colored = new ColoredTransaction(frame.TransactionId, frame.Transaction, spentCoins.ToArray(), issuanceScriptPubkey); coloreds.Push(colored); await repo.PutAsync(frame.TransactionId, colored).ConfigureAwait(false); } if (coloreds.Count != 1) { throw new InvalidOperationException("Colored stack length != 1, this is a NBitcoinBTG bug, please contact us."); } return(coloreds.Pop()); }
public Task PutAsync(uint256 txId, ColoredTransaction tx) { return(_Repository.PutAsync(GetId(txId), tx)); }
public static void Put(this IColoredTransactionRepository repo, uint256 txId, ColoredTransaction tx) { try { repo.PutAsync(txId, tx).Wait(); } catch (AggregateException aex) { ExceptionDispatchInfo.Capture(aex.InnerException).Throw(); } }
public Task PutAsync(uint256 txId, ColoredTransaction tx) { return(_Inner.PutAsync(txId, tx)); }