lbcwallet/wallet/createtx.go

417 lines
13 KiB
Go
Raw Normal View History

// Copyright (c) 2013-2017 The btcsuite developers
// Copyright (c) 2015-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package wallet
import (
"fmt"
2021-03-29 16:36:41 +02:00
"math/rand"
"sort"
"github.com/lbryio/lbcd/btcec"
"github.com/lbryio/lbcd/txscript"
"github.com/lbryio/lbcd/wire"
btcutil "github.com/lbryio/lbcutil"
"github.com/lbryio/lbcwallet/waddrmgr"
"github.com/lbryio/lbcwallet/wallet/txauthor"
"github.com/lbryio/lbcwallet/wallet/txsizes"
"github.com/lbryio/lbcwallet/walletdb"
"github.com/lbryio/lbcwallet/wtxmgr"
)
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
// byAmount defines the methods needed to satisify sort.Interface to
// sort credits by their output amount.
type byAmount []wtxmgr.Credit
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
func (s byAmount) Len() int { return len(s) }
func (s byAmount) Less(i, j int) bool { return s[i].Amount < s[j].Amount }
func (s byAmount) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
func makeInputSource(eligible []wtxmgr.Credit) txauthor.InputSource {
// Current inputs and their total value. These are closed over by the
// returned input source and reused across multiple calls.
currentTotal := btcutil.Amount(0)
currentInputs := make([]*wire.TxIn, 0, len(eligible))
currentScripts := make([][]byte, 0, len(eligible))
currentInputValues := make([]btcutil.Amount, 0, len(eligible))
return func(target btcutil.Amount) (btcutil.Amount, []*wire.TxIn,
[]btcutil.Amount, [][]byte, error) {
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
for currentTotal < target && len(eligible) != 0 {
nextCredit := &eligible[0]
eligible = eligible[1:]
nextInput := wire.NewTxIn(&nextCredit.OutPoint, nil, nil)
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
currentTotal += nextCredit.Amount
currentInputs = append(currentInputs, nextInput)
currentScripts = append(currentScripts, nextCredit.PkScript)
currentInputValues = append(currentInputValues, nextCredit.Amount)
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
}
return currentTotal, currentInputs, currentInputValues, currentScripts, nil
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
}
}
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
// secretSource is an implementation of txauthor.SecretSource for the wallet's
// address manager.
type secretSource struct {
*waddrmgr.Manager
addrmgrNs walletdb.ReadBucket
}
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
func (s secretSource) GetKey(addr btcutil.Address) (*btcec.PrivateKey, bool, error) {
ma, err := s.Address(s.addrmgrNs, addr)
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
if err != nil {
return nil, false, err
}
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
mpka, ok := ma.(waddrmgr.ManagedPubKeyAddress)
if !ok {
e := fmt.Errorf("managed address type for %v is `%T` but "+
"want waddrmgr.ManagedPubKeyAddress", addr, ma)
return nil, false, e
}
privKey, err := mpka.PrivKey()
if err != nil {
return nil, false, err
}
return privKey, ma.Compressed(), nil
}
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
func (s secretSource) GetScript(addr btcutil.Address) ([]byte, error) {
ma, err := s.Address(s.addrmgrNs, addr)
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
if err != nil {
return nil, err
}
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
msa, ok := ma.(waddrmgr.ManagedScriptAddress)
if !ok {
e := fmt.Errorf("managed address type for %v is `%T` but "+
"want waddrmgr.ManagedScriptAddress", addr, ma)
return nil, e
}
return msa.Script()
}
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
// txToOutputs creates a signed transaction which includes each output from
// outputs. Previous outputs to redeem are chosen from the passed account's
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
// UTXO set and minconf policy. An additional output may be added to return
// change to the wallet. This output will have an address generated from the
// given key scope and account. If a key scope is not specified, the address
// will always be generated from the P2WKH key scope. An appropriate fee is
// included based on the wallet's current relay fee. The wallet must be
// unlocked to create the transaction.
//
// NOTE: The dryRun argument can be set true to create a tx that doesn't alter
// the database. A tx created with this set to true will intentionally have no
// input scripts added and SHOULD NOT be broadcasted.
func (w *Wallet) txToOutputs(outputs []*wire.TxOut, keyScope *waddrmgr.KeyScope,
2021-03-29 16:36:41 +02:00
account uint32, minconf int32, feeSatPerKb btcutil.Amount,
coinSelectionStrategy CoinSelectionStrategy, dryRun bool) (
*txauthor.AuthoredTx, error) {
Modernize the RPC server. This is a rather monolithic commit that moves the old RPC server to its own package (rpc/legacyrpc), introduces a new RPC server using gRPC (rpc/rpcserver), and provides the ability to defer wallet loading until request at a later time by an RPC (--noinitialload). The legacy RPC server remains the default for now while the new gRPC server is not enabled by default. Enabling the new server requires setting a listen address (--experimenalrpclisten). This experimental flag is used to effectively feature gate the server until it is ready to use as a default. Both RPC servers can be run at the same time, but require binding to different listen addresses. In theory, with the legacy RPC server now living in its own package it should become much easier to unit test the handlers. This will be useful for any future changes to the package, as compatibility with Core's wallet is still desired. Type safety has also been improved in the legacy RPC server. Multiple handler types are now used for methods that do and do not require the RPC client as a dependency. This can statically help prevent nil pointer dereferences, and was very useful for catching bugs during refactoring. To synchronize the wallet loading process between the main package (the default) and through the gRPC WalletLoader service (with the --noinitialload option), as well as increasing the loose coupling of packages, a new wallet.Loader type has been added. All creating and loading of existing wallets is done through a single Loader instance, and callbacks can be attached to the instance to run after the wallet has been opened. This is how the legacy RPC server is associated with a loaded wallet, even after the wallet is loaded by a gRPC method in a completely unrelated package. Documentation for the new RPC server has been added to the rpc/documentation directory. The documentation includes a specification for the new RPC API, addresses how to make changes to the server implementation, and provides short example clients in several different languages. Some of the new RPC methods are not implementated exactly as described by the specification. These are considered bugs with the implementation, not the spec. Known bugs are commented as such.
2015-06-01 21:57:50 +02:00
chainClient, err := w.requireChainClient()
if err != nil {
return nil, err
}
// Get current block's height and hash.
bs, err := chainClient.BlockStamp()
if err != nil {
return nil, err
}
var tx *txauthor.AuthoredTx
err = walletdb.Update(w.db, func(dbtx walletdb.ReadWriteTx) error {
addrmgrNs, changeSource, err := w.addrMgrWithChangeSource(
dbtx, keyScope, account,
)
if err != nil {
return err
2021-03-29 16:36:41 +02:00
}
eligible, err := w.findEligibleOutputs(
dbtx, keyScope, account, minconf, bs,
)
if err != nil {
return err
}
2021-03-29 16:36:41 +02:00
var inputSource txauthor.InputSource
switch coinSelectionStrategy {
// Pick largest outputs first.
case CoinSelectionLargest:
sort.Sort(sort.Reverse(byAmount(eligible)))
inputSource = makeInputSource(eligible)
// Select coins at random. This prevents the creation of ever
// smaller utxos over time that may never become economical to
// spend.
case CoinSelectionRandom:
// Skip inputs that do not raise the total transaction
// output value at the requested fee rate.
var positivelyYielding []wtxmgr.Credit
for _, output := range eligible {
output := output
if !inputYieldsPositively(&output, feeSatPerKb) {
continue
}
positivelyYielding = append(
positivelyYielding, output,
)
}
rand.Shuffle(len(positivelyYielding), func(i, j int) {
positivelyYielding[i], positivelyYielding[j] =
positivelyYielding[j], positivelyYielding[i]
})
inputSource = makeInputSource(positivelyYielding)
}
tx, err = txauthor.NewUnsignedTransaction(
outputs, feeSatPerKb, inputSource, changeSource,
)
if err != nil {
return err
}
// Randomize change position, if change exists, before signing.
// This doesn't affect the serialize size, so the change amount
// will still be valid.
if tx.ChangeIndex >= 0 {
tx.RandomizeChangePosition()
}
// If a dry run was requested, we return now before adding the
// input scripts, and don't commit the database transaction.
// By returning an error, we make sure the walletdb.Update call
// rolls back the transaction. But we'll react to this specific
// error outside of the DB transaction so we can still return
// the produced chain TX.
if dryRun {
return walletdb.ErrDryRunRollBack
}
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
err = tx.AddAllInputScripts(
secretSource{w.Manager, addrmgrNs},
)
if err != nil {
return err
}
err = validateMsgTx(
tx.Tx, tx.PrevScripts, tx.PrevInputValues,
)
if err != nil {
return err
}
if tx.ChangeIndex >= 0 && account == waddrmgr.ImportedAddrAccount {
changeAmount := btcutil.Amount(
tx.Tx.TxOut[tx.ChangeIndex].Value,
)
log.Warnf("Spend from imported account produced "+
"change: moving %v from imported account into "+
"default account.", changeAmount)
}
// Finally, we'll request the backend to notify us of the
// transaction that pays to the change address, if there is one,
// when it confirms.
if tx.ChangeIndex >= 0 {
changePkScript := tx.Tx.TxOut[tx.ChangeIndex].PkScript
_, addrs, _, err := txscript.ExtractPkScriptAddrs(
changePkScript, w.chainParams,
)
if err != nil {
return err
}
if err := chainClient.NotifyReceived(addrs); err != nil {
return err
}
}
return nil
})
if err != nil && err != walletdb.ErrDryRunRollBack {
return nil, err
}
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
return tx, nil
}
func (w *Wallet) findEligibleOutputs(dbtx walletdb.ReadTx,
keyScope *waddrmgr.KeyScope, account uint32, minconf int32,
bs *waddrmgr.BlockStamp) ([]wtxmgr.Credit, error) {
addrmgrNs := dbtx.ReadBucket(waddrmgrNamespaceKey)
txmgrNs := dbtx.ReadBucket(wtxmgrNamespaceKey)
unspent, err := w.TxStore.UnspentOutputs(txmgrNs)
if err != nil {
return nil, err
}
2015-04-06 21:03:24 +02:00
// TODO: Eventually all of these filters (except perhaps output locking)
// should be handled by the call to UnspentOutputs (or similar).
// Because one of these filters requires matching the output script to
// the desired account, this change depends on making wtxmgr a waddrmgr
2021-03-24 14:43:24 +01:00
// dependency and requesting unspent outputs for a single account.
2015-04-06 21:03:24 +02:00
eligible := make([]wtxmgr.Credit, 0, len(unspent))
for i := range unspent {
2015-04-06 21:03:24 +02:00
output := &unspent[i]
2015-04-06 21:03:24 +02:00
// Only include this output if it meets the required number of
// confirmations. Coinbase transactions must have have reached
// maturity before their outputs may be spent.
if !confirmed(minconf, output.Height, bs.Height) {
continue
}
if output.FromCoinBase {
target := int32(w.chainParams.CoinbaseMaturity)
2015-04-06 21:03:24 +02:00
if !confirmed(target, output.Height, bs.Height) {
continue
}
2015-04-06 21:03:24 +02:00
}
2015-04-06 21:03:24 +02:00
// Locked unspent outputs are skipped.
if w.LockedOutpoint(output.OutPoint) {
continue
}
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
// Only include the output if it is associated with the passed
// account.
//
// TODO: Handle multisig outputs by determining if enough of the
// addresses are controlled.
_, addrs, _, err := txscript.ExtractPkScriptAddrs(
2015-04-06 21:03:24 +02:00
output.PkScript, w.chainParams)
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
if err != nil || len(addrs) != 1 {
2015-04-06 21:03:24 +02:00
continue
}
if isStake(output.PkScript) {
continue
}
scopedMgr, addrAcct, err := w.Manager.AddrAccount(addrmgrNs, addrs[0])
if err != nil {
continue
}
if keyScope != nil && scopedMgr.Scope() != *keyScope {
continue
}
if addrAcct != account {
2015-04-06 21:03:24 +02:00
continue
}
eligible = append(eligible, *output)
}
return eligible, nil
}
2021-03-29 16:36:41 +02:00
// inputYieldsPositively returns a boolean indicating whether this input yields
// positively if added to a transaction. This determination is based on the
// best-case added virtual size. For edge cases this function can return true
// while the input is yielding slightly negative as part of the final
// transaction.
func inputYieldsPositively(credit *wtxmgr.Credit, feeRatePerKb btcutil.Amount) bool {
inputSize := txsizes.GetMinInputVirtualSize(credit.PkScript)
inputFee := feeRatePerKb * btcutil.Amount(inputSize) / 1000
return inputFee < credit.Amount
}
// addrMgrWithChangeSource returns the address manager bucket and a change
// source that returns change addresses from said address manager. The change
// addresses will come from the specified key scope and account, unless a key
// scope is not specified. In that case, change addresses will always come from
// the P2WKH key scope.
func (w *Wallet) addrMgrWithChangeSource(dbtx walletdb.ReadWriteTx,
changeKeyScope *waddrmgr.KeyScope, account uint32) (
walletdb.ReadWriteBucket, *txauthor.ChangeSource, error) {
// Determine the address type for change addresses of the given account.
if changeKeyScope == nil {
changeKeyScope = &waddrmgr.KeyScopeBIP0084
}
addrType := waddrmgr.ScopeAddrMap[*changeKeyScope].InternalAddrType
// It's possible for the account to have an address schema override, so
// prefer that if it exists.
addrmgrNs := dbtx.ReadWriteBucket(waddrmgrNamespaceKey)
scopeMgr, err := w.Manager.FetchScopedKeyManager(*changeKeyScope)
if err != nil {
return nil, nil, err
}
accountInfo, err := scopeMgr.AccountProperties(addrmgrNs, account)
if err != nil {
return nil, nil, err
}
if accountInfo.AddrSchema != nil {
addrType = accountInfo.AddrSchema.InternalAddrType
}
// Compute the expected size of the script for the change address type.
var scriptSize int
switch addrType {
case waddrmgr.PubKeyHash:
scriptSize = txsizes.P2PKHPkScriptSize
case waddrmgr.NestedWitnessPubKey:
scriptSize = txsizes.NestedP2WPKHPkScriptSize
case waddrmgr.WitnessPubKey:
scriptSize = txsizes.P2WPKHPkScriptSize
}
newChangeScript := func() ([]byte, error) {
// Derive the change output script. As a hack to allow spending
// from the imported account, change addresses are created from
// account 0.
var (
changeAddr btcutil.Address
err error
)
if account == waddrmgr.ImportedAddrAccount {
changeAddr, err = w.newChangeAddress(
addrmgrNs, 0, *changeKeyScope,
)
} else {
changeAddr, err = w.newChangeAddress(
addrmgrNs, account, *changeKeyScope,
)
}
if err != nil {
return nil, err
}
return txscript.PayToAddrScript(changeAddr)
}
return addrmgrNs, &txauthor.ChangeSource{
ScriptSize: scriptSize,
NewScript: newChangeScript,
}, nil
}
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
// validateMsgTx verifies transaction input scripts for tx. All previous output
// scripts from outputs redeemed by the transaction, in the same order they are
// spent, must be passed in the prevScripts slice.
func validateMsgTx(tx *wire.MsgTx, prevScripts [][]byte, inputValues []btcutil.Amount) error {
hashCache := txscript.NewTxSigHashes(tx)
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
for i, prevScript := range prevScripts {
vm, err := txscript.NewEngine(prevScript, tx, i,
txscript.StandardVerifyFlags, nil, hashCache, int64(inputValues[i]))
if err != nil {
return fmt.Errorf("cannot create script engine: %s", err)
}
Refactor wallet transaction creation code. This began as a change to improve the fee calculation code and evolved into a much larger refactor which improves the readability and modularity of all of the transaction creation code. Transaction fee calculations have been switched from full increments of the relay fee to a proportion based on the transaction size. This means that for a relay fee of 1e3 satoshis/kB, a 500 byte transaction is only required to pay a 5e2 satoshi fee and a 1500 byte transaction only need pay a 1.5e3 fee. The previous code would end up estimating these fees to be 1e3 and 2e3 respectively. Because the previous code would add more fee than needed in almost every case, the transaction size estimations were optimistic (best/smallest case) and signing was done in a loop where the fee was incremented by the relay fee again each time the actual size of the signed transaction rendered the fee too low. This has switched to using worst case transaction size estimates rather than best case, and signing is only performed once. Transaction input signature creation has switched from using txscript.SignatureScript to txscript.SignTxOutput. The new API is able to redeem outputs other than just P2PKH, so the previous restrictions about P2SH outputs being unspendable (except through the signrawtransaction RPC) no longer hold. Several new public packages have been added: wallet/txauthor - transaction authoring and signing wallet/txfees - fee estimations and change output inclusion wallet/txrules - simple consensus and mempool policy rule checks Along with some internal packages: wallet/internal/txsizes - transaction size estimation internal/helpers - context free convenience functions The txsizes package is internal as the estimations it provides are specific for the algorithms used by these new packages.
2016-02-28 05:30:56 +01:00
err = vm.Execute()
if err != nil {
return fmt.Errorf("cannot validate transaction: %s", err)
}
}
return nil
}