private HistoricalTransactionDto MapToHistoricalTransaction(BitcoinTransaction tx, string requestedAddress)
        {
            var isSending = tx.Inputs.Where(p => p.Address == requestedAddress).Sum(p => p.Value) >=
                            tx.Outputs.Where(p => p.Address == requestedAddress).Sum(p => p.Value);
            string from;
            string to;
            long   amount;

            if (isSending)
            {
                from = requestedAddress;
                to   = tx.Outputs.Select(o => o.Address).FirstOrDefault(o => o != null && o != requestedAddress) ??
                       requestedAddress;
                amount = tx.Outputs.Where(o => o.Address != requestedAddress).Sum(o => o.Value);
            }
            else
            {
                to   = requestedAddress;
                from = tx.Inputs.Select(o => o.Address).FirstOrDefault(o => o != null && o != requestedAddress) ??
                       requestedAddress;
                amount = tx.Outputs.Where(o => o.Address == requestedAddress).Sum(o => o.Value);
            }

            return(new HistoricalTransactionDto
            {
                TxHash = tx.Hash,
                IsSending = isSending,
                AmountSatoshi = amount,
                FromAddress = from,
                AssetId = Constants.Assets.Bitcoin.AssetId,
                ToAddress = to,
                TimeStamp = tx.Timestamp
            });
        }
Exemplo n.º 2
0
        /// <summary>
        /// Reads a single transaction off the blockchain in sequential order
        ///
        /// thanks
        /// https://en.bitcoin.it/wiki/Protocol_specification#block
        /// http://james.lab6.com/2012/01/12/bitcoin-285-bytes-that-changed-the-world/
        /// https://code.google.com/p/blockchain/source/browse/trunk/BlockChain.h
        /// </summary>
        public Boolean Read()
        {
            var newBlock = new BitcoinBlock {
                MagicBytes = Dequeue(4)
            };

            if (BitConverter.ToUInt32(newBlock.MagicBytes, 0) != 3652501241)
            {
                throw new Exception("Invalid magic number at the start of this block");
            }

            newBlock.BlockSize          = BitConverter.ToUInt32(Dequeue(4), 0);
            newBlock.BlockFormatVersion = BitConverter.ToUInt32(Dequeue(4), 0);
            newBlock.PreviousBlockHash  = ReverseArray(Dequeue(32));
            newBlock.MerkleRoot         = ReverseArray(Dequeue(32));
            newBlock.TimeStamp          = Helper.UnixToDateTime(BitConverter.ToUInt32(Dequeue(4), 0));
            newBlock.Bits             = BitConverter.ToUInt32(Dequeue(4), 0);
            newBlock.Nonce            = BitConverter.ToUInt32(Dequeue(4), 0);
            newBlock.TransactionCount = ReadVariableLengthInteger(Dequeue(1));

            for (var t = 0; t < newBlock.TransactionCount; t++)
            {
                var newTransaction = new BitcoinTransaction();
                newTransaction.TransactionVersionNumber = BitConverter.ToUInt32(Dequeue(4), 0);
                newTransaction.InputCount = ReadVariableLengthInteger(Dequeue(1));

                for (var i = 0; i < newTransaction.InputCount; i++)
                {
                    var newInput = new BitcoinInput();
                    newInput.InputTransactionHash  = Dequeue(32);
                    newInput.InputTransactionIndex = BitConverter.ToUInt32(Dequeue(4), 0);
                    newInput.ResponseScriptLength  = ReadVariableLengthInteger(Dequeue(1));
                    newInput.ResponseScript        = Dequeue((int)newInput.ResponseScriptLength);
                    newInput.SequenceNumber        = BitConverter.ToUInt32(Dequeue(4), 0);
                    newTransaction.Inputs.Add(newInput);
                }

                newTransaction.OutputCount = ReadVariableLengthInteger(Dequeue(1));

                for (var o = 0; o < newTransaction.OutputCount; o++)
                {
                    var newOutput = new BitcoinOutput();
                    newOutput.OutputValue           = BitConverter.ToUInt64(Dequeue(8), 0);
                    newOutput.ChallengeScriptLength = ReadVariableLengthInteger(Dequeue(1));
                    newOutput.ChallengeScript       = Dequeue((int)newOutput.ChallengeScriptLength);
                    newOutput.EcdsaPublickey        = ExtractPublicKey(newOutput.ChallengeScript);
                    newOutput.BitcoinAddress        = ComputeBitcoinAddress(newOutput.EcdsaPublickey); // todo: expensive operation, should it be a feature flag?
                    newTransaction.Outputs.Add(newOutput);
                }

                newTransaction.LockTime = BitConverter.ToUInt32(Dequeue(4), 0);
                newBlock.Transactions.Add(newTransaction);
            }

            CurrentBlock = newBlock;
            return(true);
        }
 /// <summary>
 /// Converts Raw Transaction hex into a JSON string representation of the transaction.
 /// </summary>
 private void SetJson()
 {
     try
     {
         BitcoinTransaction btx = Transaction.DecodeRawTx(RawTx);
         TxJson = JsonConvert.SerializeObject(btx, Formatting.Indented);
     }
     catch (Exception ex)
     {
         TxJson = "Not a Valid Transaction hex" + Environment.NewLine + ex.ToString();
     }
 }
        public static async Task <BitcoinTransaction> SignBitcoinTransaction(Page parentPage, BitcoinTransaction bitcoinTX)
        {
            _parentPage = parentPage;
            _bitcoinTX  = bitcoinTX;
            _waitHandle.Reset();
            var deviceCommPage = new DeviceCommPage(CommFunction.SignBitcoinTx);
            await _parentPage.Navigation.PushModalAsync(deviceCommPage);

            await Task.Run(() => _waitHandle.WaitOne());

            return(_bitcoinTX);
        }
Exemplo n.º 5
0
        public static void Main(string[] args)
        {
            string             hash        = "0ade9b2864672074864c1d509ac427ffdcf16fe983ef6ebe8b0606afd3fb50a4";
            BitcoinTransaction transaction = BlockchainAPI.GetTransaction(hash);

            Console.WriteLine("Block Number = {0}", transaction.BlockHeight);

            BitcoinBlock latestBlock = BlockchainAPI.GetLatestBlock();

            Console.WriteLine("LatestBlock = {0}", latestBlock.BlockHeight);

            Console.WriteLine("Number of Confirmations = {0}", latestBlock.BlockHeight - transaction.BlockHeight);

            Console.ReadLine();
        }
Exemplo n.º 6
0
        /// <summary>
        /// Deserialize the transaction hex string.
        /// </summary>
        /// <param name="tx">Transaction hex string</param>
        /// <returns>Bitcoin Transaction</returns>
        public static BitcoinTransaction DecodeRawTx(string tx)
        {
            BitcoinTransaction btx = new BitcoinTransaction();
            int index = 0;

            // 1) 4 byte - version
            string version = tx.Substring(index, 8);

            btx.Version = (UInt32)NumberConversions.HexToUInt(version);
            index      += 8;

            // 2) ? byte - tx_in count (CompactSize uint)
            btx.TxInCount = NumberConversions.ReadCompactSize(tx, ref index);

            bool isSigned = true;
            bool isRbf    = false;

            // Initialize the array
            btx.TxInList = new TxIn[btx.TxInCount];
            for (UInt64 i = 0; i < btx.TxInCount; i++)
            {
                TxIn temp = new TxIn();
                // 3) 32 byte - TX hash (reverse)
                temp.TxId = tx.Substring(index, 64);
                temp.TxId = ReverseTx(temp.TxId);
                index    += 64;

                // 4) 4 byte - output Index
                string outIndex = tx.Substring(index, 8);
                temp.OutIndex = (UInt32)NumberConversions.HexToUInt(outIndex);
                index        += 8;

                // 5) ? byte - scriptSig length (CompactSize uint) (Maximum value is 10,000 bytes)
                string scriptSigLength = tx.Substring(index, 2);
                temp.ScriptSigLength = (int)NumberConversions.ReadCompactSize(tx, ref index);

                // 6) ? byte - scriptSig or a placeholder for unsigned (can be empty too)
                temp.ScriptSig = tx.Substring(index, temp.ScriptSigLength * 2);
                index         += temp.ScriptSigLength * 2;

                //7) 4 byte - sequence - max is 0xffffffff - can change for RBF transactions
                string sequence = tx.Substring(index, 8);
                temp.Sequence = (UInt32)NumberConversions.HexToUInt(sequence);
                index        += 8;

                btx.TxInList[i] = temp;

                // Check to see if all the inputs are signed
                if (temp.ScriptSigLength <= 25)
                {
                    isSigned = false;
                }

                // Check for opt-in Replace By Fee
                if (temp.Sequence != UInt32.MaxValue)
                {
                    isRbf = true;
                }
            }
            // Set transaction sign and RBF status.
            btx.Status = (isSigned) ? BitcoinTransaction.TxStatus.Signed : BitcoinTransaction.TxStatus.Unsigned;
            btx.IsRbf  = isRbf;

            //8) ? byte - tx_out count (compactSize uint)
            btx.TxOutCount = NumberConversions.ReadCompactSize(tx, ref index);

            // Initialize the array
            btx.TxOutList = new TxOut[btx.TxOutCount];
            for (UInt64 i = 0; i < btx.TxOutCount; i++)
            {
                TxOut temp = new TxOut();

                //9) 8 byte - amout to transfer
                string amount = tx.Substring(index, 16);
                temp.Amount = NumberConversions.HexToUInt(amount);
                index      += 16;

                //10) ? byte - pk_script length (compactSize uint)
                string pkScriptLength = tx.Substring(index, 2);
                temp.PkScriptLength = (Int32)NumberConversions.HexToUInt(pkScriptLength);
                index += 2;

                //11) ? byte - pk_script
                temp.PkScript = tx.Substring(index, temp.PkScriptLength * 2);
                index        += temp.PkScriptLength * 2;

                btx.TxOutList[i] = temp;
            }

            //12) 4 byte - lock time
            string lockTime = tx.Substring(index, 8);

            btx.LockTime = (UInt32)NumberConversions.HexToUInt(lockTime);
            index       += 8;

            // If the transaction is signed, then it has a TxId
            if (isSigned)
            {
                btx.TxId = BitcoinConversions.GetTxId(tx);
            }

            return(btx);
        }
Exemplo n.º 7
0
        public async Task <byte[]> SignTransactionAsync(BitcoinTransaction transaction)
        {
            var txDic      = new Dictionary <string, TransactionType>();
            var unsignedTx = new TransactionType
            {
                Version      = transaction.Version,
                InputsCnt    = (uint)transaction.Inputs.Count,  // must be exact number of Inputs count
                OutputsCnt   = (uint)transaction.Outputs.Count, // must be exact number of Outputs count
                LockTime     = transaction.LockTime,
                ExtraData    = transaction.ExtraData,
                ExtraDataLen = transaction.ExtraData == null ? 0 : (uint)transaction.ExtraData.Length
            };

            CopyInputs(transaction.Inputs, unsignedTx.Inputs, false);
            CopyOutputs(transaction.Outputs, unsignedTx.Outputs);

            txDic.Add("unsigned", unsignedTx);

            foreach (var txInput in transaction.Inputs)
            {
                BitcoinTransaction prevTran = txInput.PrevTransaction;
                var tx = new TransactionType
                {
                    Version    = prevTran.Version,
                    LockTime   = prevTran.LockTime,
                    InputsCnt  = (uint)prevTran.Inputs.Count,
                    OutputsCnt = (uint)prevTran.Outputs.Count,
                };
                CopyInputs(prevTran.Inputs, tx.Inputs, true);
                CopyBinOutputs(prevTran.Outputs, tx.BinOutputs);

                txDic.Add(txInput.PrevHash.ToHex(), tx);
            }

            var serializedTx = new List <byte>();

            var request = await SendMessageAsync <TxRequest, SignTx>(new SignTx
            {
                CoinName     = transaction.CoinName,
                InputsCount  = (uint)transaction.Inputs.Count,
                OutputsCount = (uint)transaction.Outputs.Count
            });

            TxAck txAck;

            // We do loop here since we need to send over and over the same transactions to trezor because his 64 kilobytes memory
            // and he will sign chunks and return part of signed chunk in serialized manner, until we receive finall type of Txrequest TxFinished
            while (request.RequestType != RequestType.Txfinished)
            {
                TransactionType currentTx;
                if ((request.Details != null) && (request.Details.TxHash != null))
                {
                    string hash = request.Details.TxHash.ToHex();
                    if (txDic.ContainsKey(hash))
                    {
                        currentTx = txDic[hash];
                    }
                    else
                    {
                        Log.Error($"Unknown hash {hash}");
                        currentTx = txDic["unsigned"];
                    }
                }
                else
                {
                    currentTx = txDic["unsigned"];
                }

                switch (request.RequestType)
                {
                case RequestType.Txinput:
                {
                    var msg = new TransactionType();
                    foreach (var input in currentTx.Inputs)
                    {
                        msg.Inputs.Add(input);
                    }
                    ;

                    txAck = new TxAck {
                        Tx = msg
                    };
                    //We send TxAck() with  TxInputs
                    request = await SendMessageAsync <TxRequest, TxAck>(txAck);

                    // Now we have to check every response is there any SerializedTx chunk
                    if (request.Serialized != null)
                    {
                        serializedTx.AddRange(request.Serialized.SerializedTx);
                    }

                    break;
                }

                case RequestType.Txoutput:
                {
                    var msg = new TransactionType();
                    if ((request.Details != null) && (request.Details.TxHash != null))
                    {
                        msg.BinOutputs.Add(currentTx.BinOutputs[(int)request.Details.RequestIndex]);
                    }
                    else
                    {
                        msg.Outputs.Add(currentTx.Outputs[(int)request.Details.RequestIndex]);
                    }

                    txAck = new TxAck {
                        Tx = msg
                    };
                    //We send TxAck()  with  TxOutputs
                    request = await SendMessageAsync <TxRequest, TxAck>(txAck);

                    // Now we have to check every response is there any SerializedTx chunk
                    if (request.Serialized != null)
                    {
                        serializedTx.AddRange(request.Serialized.SerializedTx);
                    }

                    break;
                }

                case RequestType.Txextradata:
                {
                    var offset = request.Details.ExtraDataOffset;
                    var length = request.Details.ExtraDataLen;
                    var msg    = new TransactionType
                    {
                        ExtraData = currentTx.ExtraData.Skip((int)offset).Take((int)length).ToArray()
                    };
                    txAck = new TxAck {
                        Tx = msg
                    };
                    //We send TxAck() with  TxInputs
                    request = await SendMessageAsync <TxRequest, TxAck>(txAck);

                    // Now we have to check every response is there any SerializedTx chunk
                    if (request.Serialized != null)
                    {
                        serializedTx.AddRange(request.Serialized.SerializedTx);
                    }
                    break;
                }

                case RequestType.Txmeta:
                {
                    var msg = new TransactionType
                    {
                        Version    = currentTx.Version,
                        LockTime   = currentTx.LockTime,
                        InputsCnt  = currentTx.InputsCnt,
                        OutputsCnt = (request.Details != null) && (request.Details.TxHash != null) ? (uint)currentTx.BinOutputs.Count : (uint)currentTx.Outputs.Count,
                        //ExtraDataLen = currentTx.ExtraData != null ? (uint)currentTx.ExtraData.Length : 0
                    };
                    txAck = new TxAck {
                        Tx = msg
                    };
                    //We send TxAck() with  TxInputs
                    request = await SendMessageAsync <TxRequest, TxAck>(txAck);

                    // Now we have to check every response is there any SerializedTx chunk
                    if (request.Serialized != null)
                    {
                        serializedTx.AddRange(request.Serialized.SerializedTx);
                    }

                    break;
                }
                }
            }
            return(serializedTx.ToArray());
        }
Exemplo n.º 8
0
        async void NextButton_Clicked(object sender, EventArgs e)
        {
            var bitcoinTransaction = new BitcoinTransaction(selectedCoin.Name);

            var bitcoinService = BitcoinService.GetBitcoinService(selectedCoin.Shortcut);
            var tx             = await bitcoinService.CreateTransactionAsync(new BitcoinTX()
            {
                Inputs = new List <BitcoinTXInput> {
                    new BitcoinTXInput {
                        Addresses = new List <string> {
                            selectedCoin.DefaultAddress
                        }
                    }
                },
                Outputs = new List <BitcoinTXOutput> {
                    new BitcoinTXOutput {
                        Addresses = new List <string> {
                            toAddressEntry.Text
                        }, Value = 100000
                    }
                }
            });

            foreach (var input in tx.Tx.Inputs)
            {
                var newInput = new BitcoinTransactionInput
                {
                    AddressNs = Repository.GetAddress(input.Addresses[0]).GetAddressPath(),
                    Amount    = (ulong)input.OutputValue,
                    PrevHash  = input.PrevHash.ToBytes(),
                    PrevIndex = (uint)input.OutputIndex,
                    Sequence  = (uint)input.Sequence
                };
                var inputTx = await bitcoinService.GetTransactionAsync(input.PrevHash);

                newInput.PrevTransaction = new BitcoinTransaction(selectedCoin.Shortcut, (uint)inputTx.Ver, (uint)inputTx.LockTime);

                foreach (var prevInput in inputTx.Inputs)
                {
                    newInput.PrevTransaction.Inputs.Add(new BitcoinTransactionInput
                    {
                        PrevHash   = prevInput.PrevHash.ToBytes(),
                        ScriptSig  = prevInput.Script.ToBytes(),
                        PrevIndex  = (uint)prevInput.OutputIndex,
                        Sequence   = (uint)prevInput.Sequence,
                        ScriptType = InputScriptType.Spendaddress
                    });
                }
                foreach (var prevOutput in inputTx.Outputs)
                {
                    newInput.PrevTransaction.Outputs.Add(new BitcoinTransactionOutput
                    {
                        Amount = (ulong)prevOutput.Value,
                        Script = prevOutput.Script.ToBytes()
                    });
                }

                bitcoinTransaction.Inputs.Add(newInput);
            }

            foreach (var output in tx.Tx.Outputs)
            {
                bitcoinTransaction.Outputs.Add(new BitcoinTransactionOutput
                {
                    Address     = output.Addresses[0],
                    Script      = output.Script.ToBytes(),
                    Amount      = (ulong)output.Value,
                    AddressType = OutputAddressType.Spend,
                    ScriptType  = OutputScriptType.Paytoscripthash,
                });
            }

            var signedTx = await DeviceCommPage.SignBitcoinTransaction(this, bitcoinTransaction);

            Log.Debug(JsonConvert.SerializeObject(signedTx));
            var txPushResult = await bitcoinService.PushRawTransactionAsync(new BitcoinTXRaw { Tx = signedTx.SerializedTx.ToHex().ToLower() });

            Log.Debug(JsonConvert.SerializeObject(txPushResult));
        }