Пример #1
0
		public static ColorMarker TryParse(Script script)
		{
			try
			{
				ColorMarker result = new ColorMarker();
				if(!result.ReadScript(script))
					return null;
				return result;
			}
			catch(EndOfStreamException)
			{
				return null;
			}
		}
Пример #2
0
		public void ReadWrite(BitcoinStream stream)
		{
			if(stream.Serializing)
			{
				if(_Marker != null)
					stream.ReadWrite(ref _Marker);
				else
					stream.ReadWrite(new Script());
			}
			else
			{
				Script script = new Script();
				stream.ReadWrite(ref script);
				if(script.Length != 0)
				{
					_Marker = new ColorMarker(script);
				}
				else
				{
				}
			}
			stream.ReadWrite(ref _Inputs);
			stream.ReadWrite(ref _Issuances);
			stream.ReadWrite(ref _Transfers);
		}
Пример #3
0
        public ColoredTransaction(uint256 txId, Transaction tx, ColoredCoin[] spentCoins, Script issuanceScriptPubkey)
            : this()
        {
            if (tx == null)
            {
                throw new ArgumentNullException("tx");
            }
            if (spentCoins == null)
            {
                throw new ArgumentNullException("spentCoins");
            }
            if (tx.IsCoinBase || tx.Inputs.Count == 0)
            {
                return;
            }
            txId = txId ?? tx.GetHash();

            Queue <ColoredEntry> previousAssetQueue = new Queue <ColoredEntry>();

            for (uint i = 0; i < tx.Inputs.Count; i++)
            {
                var txin      = tx.Inputs[i];
                var prevAsset = spentCoins.FirstOrDefault(s => s.Outpoint == txin.PrevOut);
                if (prevAsset != null)
                {
                    var input = new ColoredEntry()
                    {
                        Index = i,
                        Asset = prevAsset.Amount
                    };
                    previousAssetQueue.Enqueue(input);
                    Inputs.Add(input);
                }
            }

            uint markerPos = 0;
            var  marker    = ColorMarker.Get(tx, out markerPos);

            if (marker == null)
            {
                return;
            }
            Marker = marker;
            if (!marker.HasValidQuantitiesCount(tx))
            {
                return;
            }

            AssetId issuedAsset = null;

            for (uint i = 0; i < markerPos; i++)
            {
                var entry = new ColoredEntry();
                entry.Index = i;
                entry.Asset = new AssetMoney(entry.Asset.Id, i >= marker.Quantities.Length ? 0 : marker.Quantities[i]);
                if (entry.Asset.Quantity == 0)
                {
                    continue;
                }

                if (issuedAsset == null)
                {
                    var txIn = tx.Inputs.FirstOrDefault();
                    if (txIn == null)
                    {
                        continue;
                    }
                    if (issuanceScriptPubkey == null)
                    {
                        throw new ArgumentException("The transaction has an issuance detected, but issuanceScriptPubkey is null.", "issuanceScriptPubkey");
                    }
                    issuedAsset = issuanceScriptPubkey.Hash.ToAssetId();
                }
                entry.Asset = new AssetMoney(issuedAsset, entry.Asset.Quantity);
                Issuances.Add(entry);
            }

            long used = 0;

            for (uint i = markerPos + 1; i < tx.Outputs.Count; i++)
            {
                var entry = new ColoredEntry();
                entry.Index = i;
                //If there are less items in the  asset quantity list  than the number of colorable outputs (all the outputs except the marker output), the outputs in excess receive an asset quantity of zero.
                entry.Asset = new AssetMoney(entry.Asset.Id, (i - 1) >= marker.Quantities.Length ? 0 : marker.Quantities[i - 1]);
                if (entry.Asset.Quantity == 0)
                {
                    continue;
                }

                //If there are less asset units in the input sequence than in the output sequence, the transaction is considered invalid and all outputs are uncolored.
                if (previousAssetQueue.Count == 0)
                {
                    Transfers.Clear();
                    Issuances.Clear();
                    return;
                }
                entry.Asset = new AssetMoney(previousAssetQueue.Peek().Asset.Id, entry.Asset.Quantity);
                var remaining = entry.Asset.Quantity;
                while (remaining != 0)
                {
                    if (previousAssetQueue.Count == 0 || previousAssetQueue.Peek().Asset.Id != entry.Asset.Id)
                    {
                        Transfers.Clear();
                        Issuances.Clear();
                        return;
                    }
                    var assertPart = Math.Min(previousAssetQueue.Peek().Asset.Quantity - used, remaining);
                    remaining = remaining - assertPart;
                    used     += assertPart;
                    if (used == previousAssetQueue.Peek().Asset.Quantity)
                    {
                        previousAssetQueue.Dequeue();
                        used = 0;
                    }
                }
                Transfers.Add(entry);
            }
        }
 public static bool HasValidColoredMarker(this Transaction tx)
 {
     return(ColorMarker.HasValidColorMarker(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 async Task <ColoredTransaction> GetAsync(uint256 txId)
        {
            try
            {
                var result = new ColoredTransaction();

                var url = string.Empty;
                if (this.network.NetworkType == NetworkType.Testnet || this.network.NetworkType == NetworkType.Regtest)
                {
                    url = string.Format("https://testnet.api.coinprism.com/v1/transactions/{0}", txId);
                }
                else
                {
                    url = string.Format("https://api.coinprism.com/v1/transactions/{0}", txId);
                }

                var req = WebRequest.CreateHttp(url);
                req.Method = "GET";

                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 (var 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()).AssetId,
                                inputs[i]["asset_quantity"].Value <ulong>());

                            result.Inputs.Add(entry);
                        }
                    }

                    var outputs = json["outputs"] as JArray;
                    if (outputs != null)
                    {
                        var issuance = true;
                        for (var 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;
                            }
                            var entry = new ColoredEntry();
                            entry.Index = (uint)i;
                            entry.Asset = new AssetMoney(
                                new BitcoinAssetId(outputs[i]["asset_id"].ToString()).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 static ColorMarker GetColoredMarker(this Transaction tx)
 {
     return(ColorMarker.Get(tx));
 }
Пример #8
0
        private static ColoredTransaction FetchColorsWithAncestorsSolved(uint256 txId, Transaction tx, IColoredTransactionRepository repo)
        {
            ColoredTransaction colored = new ColoredTransaction();

            Queue <ColoredEntry> previousAssetQueue = new Queue <ColoredEntry>();

            for (int i = 0; i < tx.Inputs.Count; i++)
            {
                var txin        = tx.Inputs[i];
                var prevColored = repo.Get(txin.PrevOut.Hash);
                if (prevColored == null)
                {
                    continue;
                }
                var prevAsset = prevColored.GetColoredEntry(txin.PrevOut.N);
                if (prevAsset != null)
                {
                    var input = new ColoredEntry()
                    {
                        Index = i,
                        Asset = prevAsset.Asset
                    };
                    previousAssetQueue.Enqueue(input);
                    colored.Inputs.Add(input);
                }
            }

            int markerPos = 0;
            var marker    = ColorMarker.Get(tx, out markerPos);

            if (marker == null)
            {
                repo.Put(txId, colored);
                return(colored);
            }
            colored.Marker = marker;
            if (!marker.HasValidQuantitiesCount(tx))
            {
                repo.Put(txId, colored);
                return(colored);
            }

            ScriptId issuedAsset = null;

            for (int i = 0; i < markerPos; i++)
            {
                var entry = new ColoredEntry();
                entry.Index          = i;
                entry.Asset.Quantity = i >= marker.Quantities.Length ? 0 : marker.Quantities[i];
                if (entry.Asset.Quantity == 0)
                {
                    continue;
                }

                if (issuedAsset == null)
                {
                    var txIn = tx.Inputs.FirstOrDefault();
                    if (txIn == null)
                    {
                        continue;
                    }
                    var prev = repo.Transactions.Get(txIn.PrevOut.Hash);
                    if (prev == null)
                    {
                        throw new TransactionNotFoundException("This 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);
                    }
                    issuedAsset = prev.Outputs[(int)txIn.PrevOut.N].ScriptPubKey.ID;
                }
                entry.Asset.Id = issuedAsset;
                colored.Issuances.Add(entry);
            }

            ulong used = 0;

            for (int i = markerPos + 1; i < tx.Outputs.Count; i++)
            {
                var entry = new ColoredEntry();
                entry.Index = i;
                //If there are less items in the  asset quantity list  than the number of colorable outputs (all the outputs except the marker output), the outputs in excess receive an asset quantity of zero.
                entry.Asset.Quantity = (i - 1) >= marker.Quantities.Length ? 0 : marker.Quantities[i - 1];
                if (entry.Asset.Quantity == 0)
                {
                    continue;
                }

                //If there are less asset units in the input sequence than in the output sequence, the transaction is considered invalid and all outputs are uncolored.
                if (previousAssetQueue.Count == 0)
                {
                    colored.Transfers.Clear();
                    colored.Issuances.Clear();
                    repo.Put(txId, colored);
                    return(colored);
                }
                entry.Asset.Id = previousAssetQueue.Peek().Asset.Id;
                var remaining = entry.Asset.Quantity;
                while (remaining != 0)
                {
                    if (previousAssetQueue.Count == 0 || previousAssetQueue.Peek().Asset.Id != entry.Asset.Id)
                    {
                        colored.Transfers.Clear();
                        colored.Issuances.Clear();
                        repo.Put(txId, colored);
                        return(colored);
                    }
                    var assertPart = Math.Min(previousAssetQueue.Peek().Asset.Quantity - used, remaining);
                    remaining = remaining - assertPart;
                    used     += assertPart;
                    if (used == previousAssetQueue.Peek().Asset.Quantity)
                    {
                        previousAssetQueue.Dequeue();
                        used = 0;
                    }
                }
                colored.Transfers.Add(entry);
            }
            repo.Put(txId, colored);
            return(colored);
        }
Пример #9
0
        public ColoredTransaction Get(uint256 txId)
        {
            try
            {
                ColoredTransaction result = new ColoredTransaction();
                WebClient          client = new WebClient();
                var str    = client.DownloadString("https://api.coinprism.com/v1/transactions/" + txId);
                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 Asset(
                            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 Asset(
                            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;
            }
        }
Пример #10
0
        public async Task <ColoredTransaction> GetAsync(uint256 txId)
        {
            try
            {
                ColoredTransaction result = new ColoredTransaction();

                String url = _network == Network.PurpleMain ? 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.PurpleTest)
//                    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;
            }
        }
Пример #11
0
			public void RestoreMemento(TransactionBuildingContext memento)
			{
				_Marker = memento._Marker == null ? null : new ColorMarker(memento._Marker.GetScript());
				Transaction = memento.Transaction.Clone();
				AdditionalFees = memento.AdditionalFees;
			}
Пример #12
0
			public ColorMarker GetColorMarker(bool issuance)
			{
				if(_Marker == null)
					_Marker = new ColorMarker();
				if(!issuance)
					EnsureMarkerInserted();
				return _Marker;
			}