示例#1
0
        public static string SignTx(string TxJSON, string extPrivateKey, bool testnet)
        {
            try
            {
                Network  ntwk    = testnet ? Network.TestNet : Network.Main;
                TxSerial txs     = Newtonsoft.Json.JsonConvert.DeserializeObject <TxSerial>(TxJSON);
                ExtKey   p2      = ExtKey.Parse(extPrivateKey);
                ExtKey   RootKey = p2;

                TransactionBuilder bldr = new TransactionBuilder();
                bldr.Send(new BitcoinPubKeyAddress(txs.ToAddress), Money.Satoshis(txs.SendAmt));
                bldr.SetChange(new BitcoinPubKeyAddress(txs.ChgAddress));
                bldr.SendFees(Money.Satoshis(txs.Fee));

                //re-add coins
                List <Coin> lstCoin = new List <Coin>();
                foreach (UTXO u in txs.InputUTXOs)
                {
                    Coin cn;
                    bldr.AddCoins(cn = new Coin(
                                      new OutPoint(new uint256(u.Tx_hash), u.Tx_pos),            //tx that funded wallet, spend this coin
                                      new TxOut(Money.Satoshis(u.Value), new BitcoinPubKeyAddress(u.Address))));
                    lstCoin.Add(cn);
                }
                Transaction tx = bldr.BuildTransaction(false);                 //will select coins

                foreach (UTXO u in txs.InputUTXOs)
                {
                    Coin cn;
                    bldr.AddCoins(cn = new Coin(
                                      new OutPoint(new uint256(u.Tx_hash), u.Tx_pos),            //tx that funded wallet, spend this coin
                                      new TxOut(Money.Satoshis(u.Value), new BitcoinPubKeyAddress(u.Address))));
                    //check if coin in spend list, else error  (should already be done in CreateTx)
                    foreach (TxIn i in tx.Inputs)
                    {
                        if (i.PrevOut == cn.Outpoint)                         //this coin is in tx
                        //sign utxo with corresponding private key
                        {
                            bldr.AddKnownSignature(new PubKey(u.PublicKey), tx.SignInput(new BitcoinSecret(RootKey.Derive((uint)u.AddrType).Derive(u.AddrIndex).PrivateKey, ntwk), cn));
                        }
                    }
                }

                Transaction txSigned = bldr.BuildTransaction(true);
                NBitcoin.Policy.TransactionPolicyError[] pe;
                bool verify = bldr.Verify(txSigned, out pe);

                string hx = txSigned.ToHex();
                return(hx);
            }
            catch (Exception ex)
            {
                string result = "ERROR: " + ex.Message;
                return(result);
            }
        }
示例#2
0
        //take in tx parameters, return tx object
        public static TxSerial CreateTx(string extPubKey, string pubToAddr, string chgAddr, int walletId, long satToSend, long fee, bool testnet)
        {
            CheckNullOrEmpty(new object[] { extPubKey, pubToAddr, ElectrumXhost },
                             new string[] { "extPubKey", "pubToAddr", "ElectrumXhost" });

            string err = "";

            if (satToSend == 0)
            {
                err += "satoshiToSend = 0, ";
            }
            if (fee == 0)
            {
                err += "satoshiFee = 0, ";
            }
            if (err != "")
            {
                throw new Exception("[CreateTx] " + err);
            }

            //get first 100+100 child address from ext pub key
            List <Tuple <string, string> > recAddrList = GetDerivedKeys(extPubKey, 0, 20, false, testnet);         //receive addresses
            List <Tuple <string, string> > chgAddrList = GetDerivedKeys(extPubKey, 0, 20, true, testnet);          //change addresses

            //TODO - create process for getting next change address, so address never used twice
            if (chgAddr == null || chgAddr == "")             //get first chg addr for extPubKey
            {
                chgAddr = chgAddrList.First().Item1;
            }

            //server status check
            string info = ElectrumX.GetServerInfo(ElectrumXhost, ElectrumXport);

            if (info == null)
            {
                throw new Exception("[CreateTx] ElectrumX Server Check Failed");
            }

            string[] recAddrListAddr = new string[recAddrList.Count];            //short address
            string[] recAddrListExt  = new string[recAddrList.Count];            //long address
            int      ctr             = 0;

            foreach (var t in recAddrList)
            {
                recAddrListAddr[ctr++] = t.Item1;                 //short
            }
            ctr = 0;
            foreach (var t in recAddrList)
            {
                recAddrListExt[ctr++] = t.Item2;                 //long - hash
            }
            string[] chgAddrListAddr = new string[recAddrList.Count];
            string[] chgAddrListExt  = new string[recAddrList.Count];
            ctr = 0;
            foreach (var t in chgAddrList)
            {
                chgAddrListAddr[ctr++] = t.Item1;
            }
            ctr = 0;
            foreach (var t in chgAddrList)
            {
                chgAddrListExt[ctr++] = t.Item2;
            }

            //get all UTXOs (unspent inputs) from receive addresses
            UTXO[] recUTXOs = ElectrumX.GetUTXOs(recAddrList, ElectrumXhost, ElectrumXport);
            UTXO.SetAddressType(recUTXOs, 0);             //receiver
            //get all UTXOs (unspent inputs) from change addresses
            UTXO[] chgUTXOs = ElectrumX.GetUTXOs(chgAddrList, ElectrumXhost, ElectrumXport);
            UTXO.SetAddressType(chgUTXOs, 1);             //change

            //start new tx
            TransactionBuilder bldr = new TransactionBuilder();

            bldr.Send(new BitcoinPubKeyAddress(pubToAddr), Money.Satoshis(satToSend)); //amount to send to recipient
            bldr.SetChange(new BitcoinPubKeyAddress(chgAddr));                         //send change to this address
            bldr.SendFees(Money.Satoshis(fee));                                        //miner (tx) fee

            //collect all UTXOs
            List <UTXO> allUTXOs = new List <UTXO>();

            allUTXOs.AddRange(recUTXOs);
            allUTXOs.AddRange(chgUTXOs);

            List <ICoin> lstTxCoins = new List <ICoin>();           //Coin is a UTXO

            //add new coin for each UTXO
            foreach (UTXO x in allUTXOs)             //tx builder will select coins from this list
            {
                BitcoinPubKeyAddress fromAddr = new BitcoinPubKeyAddress(x.Address);
                NBitcoin.Coin        cn       = null;
                //create new coin from UTXO
                bldr.AddCoins(cn = new NBitcoin.Coin(
                                  new OutPoint(new uint256(x.Tx_hash), x.Tx_pos),              //tx that funded wallet, spend this coin
                                  new TxOut(Money.Satoshis(x.Value), fromAddr.ScriptPubKey))); //specify full coin amount, else SetChange ignored
                lstTxCoins.Add(cn);                                                            //add coin to transaction, may not be used
                x.tmp = cn;                                                                    //link UTXO with coin
            }

            List <UTXO> usedUTXOs = new List <UTXO>();              //coins actually used in tx

            NBitcoin.Transaction tx = bldr.BuildTransaction(false); //sort\filter coins, some coins will not be needed\used
            //coin objects not stored in tx, so we need to determine which coins were used
            //scan tx inputs for matching coins, ignore other coins
            foreach (UTXO u in allUTXOs)
            {
                foreach (TxIn i in tx.Inputs)
                {
                    if (i.PrevOut == ((NBitcoin.Coin)u.tmp).Outpoint) //this coin in tx
                    {
                        usedUTXOs.Add(u);                             //this UTXO will be used\spent in tx
                    }
                }
            }
            //populate return object
            TxSerial txs = new TxSerial()
            {
                SendAmt      = satToSend,
                Fee          = fee,
                ExtPublicKey = extPubKey,
                ToAddress    = pubToAddr,
                ChgAddress   = chgAddr,
                WalletId     = walletId
            };
            txs.ExtPublicKey = extPubKey;

            foreach (UTXO u in usedUTXOs)
            {
                u.tmp = null;                 //don't serialize coin object, will rebuild coins in signing process
            }
            txs.InputUTXOs = new List <UTXO>();
            txs.InputUTXOs.AddRange(usedUTXOs);
            //string jsn = Newtonsoft.Json.JsonConvert.SerializeObject(txs, Newtonsoft.Json.Formatting.Indented);
            return(txs);
        }
示例#3
0
        public static string CreateTxJSON(string extPubKey, string pubToAddr, string chgAddr, int walletId, long satToSend, long fee, bool testnet)
        {
            TxSerial ts = CreateTx(extPubKey, pubToAddr, chgAddr, walletId, satToSend, fee, testnet);

            return(Newtonsoft.Json.JsonConvert.SerializeObject(ts, Newtonsoft.Json.Formatting.Indented));
        }