Пример #1
0
 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);
        }
Пример #4
0
        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 NBitcoin bug, please contact us.");
            }
            return(coloreds.Pop());
        }
 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();
     }
 }
Пример #6
0
 public Task PutAsync(uint256 txId, ColoredTransaction tx)
 {
     return(_Inner.PutAsync(txId, tx));
 }
Пример #7
0
 public Task PutAsync(uint256 txId, ColoredTransaction tx)
 {
     return(_Repository.PutAsync(GetId(txId), tx));
 }
        public async Task <ColoredTransaction> GetAsync(uint256 txId)
        {
            try
            {
                ColoredTransaction result = new ColoredTransaction();
                using (HttpClient client = new HttpClient())
                {
                    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);

                    var response = await client.GetAsync(url).ConfigureAwait(false);

                    if (response.StatusCode != HttpStatusCode.OK)
                    {
                        return(null);
                    }
                    var str = await response.Content.ReadAsStringAsync().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));
 }
Пример #10
0
 public Task PutAsync(uint256 txId, ColoredTransaction tx)
 {
     return(Task.FromResult <bool>(true));
 }