/// <summary>
 /// Calculates the sum of the outputs that are sending coins to a key in the wallet. The flag controls whether to
 /// include spent outputs or not.
 /// </summary>
 internal ulong GetValueSentToMe(Wallet wallet, bool includeSpent)
 {
     // This is tested in WalletTest.
     var v = 0UL;
     foreach (var o in _outputs)
     {
         if (!o.IsMine(wallet)) continue;
         if (!includeSpent && !o.IsAvailableForSpending) continue;
         v += o.Value;
     }
     return v;
 }
        /// <summary>
        /// Once a transaction has some inputs and outputs added, the signatures in the inputs can be calculated. The
        /// signature is over the transaction itself, to prove the redeemer actually created that transaction,
        /// so we have to do this step last.
        /// </summary>
        /// <remarks>
        /// This method is similar to SignatureHash in script.cpp
        /// </remarks>
        /// <param name="hashType">This should always be set to SigHash.ALL currently. Other types are unused. </param>
        /// <param name="wallet">A wallet is required to fetch the keys needed for signing.</param>
        /// <exception cref="ScriptException"/>
        public void SignInputs(SigHash hashType, Wallet wallet)
        {
            Debug.Assert(_inputs.Count > 0);
            Debug.Assert(_outputs.Count > 0);

            // I don't currently have an easy way to test other modes work, as the official client does not use them.
            Debug.Assert(hashType == SigHash.All);

            // The transaction is signed with the input scripts empty except for the input we are signing. In the case
            // where addInput has been used to set up a new transaction, they are already all empty. The input being signed
            // has to have the connected OUTPUT program in it when the hash is calculated!
            //
            // Note that each input may be claiming an output sent to a different key. So we have to look at the outputs
            // to figure out which key to sign with.

            var signatures = new byte[_inputs.Count][];
            var signingKeys = new EcKey[_inputs.Count];
            for (var i = 0; i < _inputs.Count; i++)
            {
                var input = _inputs[i];
                Debug.Assert(input.ScriptBytes.Length == 0, "Attempting to sign a non-fresh transaction");
                // Set the input to the script of its output.
                input.ScriptBytes = input.Outpoint.ConnectedPubKeyScript;
                // Find the signing key we'll need to use.
                var connectedPubKeyHash = input.Outpoint.ConnectedPubKeyHash;
                var key = wallet.FindKeyFromPubHash(connectedPubKeyHash);
                // This assert should never fire. If it does, it means the wallet is inconsistent.
                Debug.Assert(key != null, "Transaction exists in wallet that we cannot redeem: " + Utils.BytesToHexString(connectedPubKeyHash));
                // Keep the key around for the script creation step below.
                signingKeys[i] = key;
                // The anyoneCanPay feature isn't used at the moment.
                const bool anyoneCanPay = false;
                var hash = HashTransactionForSignature(hashType, anyoneCanPay);
                // Set the script to empty again for the next input.
                input.ScriptBytes = TransactionInput.EmptyArray;

                // Now sign for the output so we can redeem it. We use the keypair to sign the hash,
                // and then put the resulting signature in the script along with the public key (below).
                using (var bos = new MemoryStream())
                {
                    bos.Write(key.Sign(hash));
                    bos.Write((byte) (((int) hashType + 1) | (anyoneCanPay ? 0x80 : 0)));
                    signatures[i] = bos.ToArray();
                }
            }

            // Now we have calculated each signature, go through and create the scripts. Reminder: the script consists of
            // a signature (over a hash of the transaction) and the complete public key needed to sign for the connected
            // output.
            for (var i = 0; i < _inputs.Count; i++)
            {
                var input = _inputs[i];
                Debug.Assert(input.ScriptBytes.Length == 0);
                var key = signingKeys[i];
                input.ScriptBytes = Script.CreateInputScript(signatures[i], key.PubKey);
            }

            // Every input is now complete.
        }
 /// <summary>
 /// Calculates the sum of the outputs that are sending coins to a key in the wallet.
 /// </summary>
 public ulong GetValueSentToMe(Wallet wallet)
 {
     return GetValueSentToMe(wallet, true);
 }
 /// <summary>
 /// Calculates the sum of the inputs that are spending coins with keys in the wallet. This requires the
 /// transactions sending coins to those keys to be in the wallet. This method will not attempt to download the
 /// blocks containing the input transactions if the key is in the wallet but the transactions are not.
 /// </summary>
 /// <returns>Sum in nanocoins.</returns>
 /// <exception cref="ScriptException"/>
 public ulong GetValueSentFromMe(Wallet wallet)
 {
     // This is tested in WalletTest.
     var v = 0UL;
     foreach (var input in _inputs)
     {
         // This input is taking value from an transaction in our wallet. To discover the value,
         // we must find the connected transaction.
         var connected = input.GetConnectedOutput(wallet.Unspent);
         if (connected == null)
             connected = input.GetConnectedOutput(wallet.Spent);
         if (connected == null)
             connected = input.GetConnectedOutput(wallet.Pending);
         if (connected == null)
             continue;
         // The connected output may be the change to the sender of a previous input sent to this wallet. In this
         // case we ignore it.
         if (!connected.IsMine(wallet))
             continue;
         v += connected.Value;
     }
     return v;
 }
Exemplo n.º 5
0
 /// <summary>
 /// Constructs a BlockChain connected to the given wallet and store. To obtain a <see cref="Wallet"/> you can construct
 /// one from scratch, or you can deserialize a saved wallet from disk using <see cref="Wallet.LoadFromFile"/>.
 /// </summary>
 /// <remarks>
 /// For the store you can use a <see cref="MemoryBlockStore"/> if you don't care about saving the downloaded data, or a
 /// <see cref="BoundedOverheadBlockStore"/> if you'd like to ensure fast start-up the next time you run the program.
 /// </remarks>
 /// <exception cref="BlockStoreException"/>
 public BlockChain(NetworkParameters @params, Wallet wallet, IBlockStore blockStore)
     : this(@params, new List<Wallet>(), blockStore)
 {
     if (wallet != null)
         AddWallet(wallet);
 }
Exemplo n.º 6
0
 /// <summary>
 /// Add a wallet to the BlockChain. Note that the wallet will be unaffected by any blocks received while it
 /// was not part of this BlockChain. This method is useful if the wallet has just been created, and its keys
 /// have never been in use, or if the wallet has been loaded along with the BlockChain
 /// </summary>
 public void AddWallet(Wallet wallet)
 {
     lock (this)
     {
         _wallets.Add(wallet);
     }
 }