212575f7d1
Add function which allows you to retrospectively label a transaction, optionally overwriting the existing label.
204 lines
5.3 KiB
Go
204 lines
5.3 KiB
Go
package wallet
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/btcsuite/btcwallet/walletdb"
|
|
"github.com/btcsuite/btcwallet/wtxmgr"
|
|
|
|
"github.com/btcsuite/btcutil"
|
|
)
|
|
|
|
var (
|
|
TstSerializedTx, _ = hex.DecodeString("010000000114d9ff358894c486b4ae11c2a8cf7851b1df64c53d2e511278eff17c22fb7373000000008c493046022100995447baec31ee9f6d4ec0e05cb2a44f6b817a99d5f6de167d1c75354a946410022100c9ffc23b64d770b0e01e7ff4d25fbc2f1ca8091053078a247905c39fce3760b601410458b8e267add3c1e374cf40f1de02b59213a82e1d84c2b94096e22e2f09387009c96debe1d0bcb2356ffdcf65d2a83d4b34e72c62eccd8490dbf2110167783b2bffffffff0280969800000000001976a914479ed307831d0ac19ebc5f63de7d5f1a430ddb9d88ac38bfaa00000000001976a914dadf9e3484f28b385ddeaa6c575c0c0d18e9788a88ac00000000")
|
|
TstTx, _ = btcutil.NewTxFromBytes(TstSerializedTx)
|
|
TstTxHash = TstTx.Hash()
|
|
)
|
|
|
|
// TestLocateBirthdayBlock ensures we can properly map a block in the chain to a
|
|
//timestamp.
|
|
func TestLocateBirthdayBlock(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// We'll use test chains of 30 blocks with a duration between two
|
|
// consecutive blocks being slightly greater than the largest margin
|
|
// allowed by locateBirthdayBlock. Doing so lets us test the method more
|
|
// effectively as there is only one block within the chain that can map
|
|
// to a timestamp (this does not apply to the first and last blocks,
|
|
// which can map to many timestamps beyond either end of chain).
|
|
const (
|
|
numBlocks = 30
|
|
blockInterval = birthdayBlockDelta + 1
|
|
)
|
|
|
|
genesisTimestamp := chainParams.GenesisBlock.Header.Timestamp
|
|
|
|
testCases := []struct {
|
|
name string
|
|
birthday time.Time
|
|
birthdayHeight int32
|
|
}{
|
|
{
|
|
name: "left-right-left-left",
|
|
birthday: genesisTimestamp.Add(8 * blockInterval),
|
|
birthdayHeight: 8,
|
|
},
|
|
{
|
|
name: "right-right-right-left",
|
|
birthday: genesisTimestamp.Add(27 * blockInterval),
|
|
birthdayHeight: 27,
|
|
},
|
|
{
|
|
name: "before start height",
|
|
birthday: genesisTimestamp.Add(-blockInterval),
|
|
birthdayHeight: 0,
|
|
},
|
|
{
|
|
name: "start height",
|
|
birthday: genesisTimestamp,
|
|
birthdayHeight: 0,
|
|
},
|
|
{
|
|
name: "end height",
|
|
birthday: genesisTimestamp.Add(numBlocks * blockInterval),
|
|
birthdayHeight: numBlocks - 1,
|
|
},
|
|
{
|
|
name: "after end height",
|
|
birthday: genesisTimestamp.Add(2 * numBlocks * blockInterval),
|
|
birthdayHeight: numBlocks - 1,
|
|
},
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
success := t.Run(testCase.name, func(t *testing.T) {
|
|
chainConn := createMockChainConn(
|
|
chainParams.GenesisBlock, numBlocks, blockInterval,
|
|
)
|
|
birthdayBlock, err := locateBirthdayBlock(
|
|
chainConn, testCase.birthday,
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("unable to locate birthday block: %v",
|
|
err)
|
|
}
|
|
if birthdayBlock.Height != testCase.birthdayHeight {
|
|
t.Fatalf("expected birthday block with height "+
|
|
"%d, got %d", testCase.birthdayHeight,
|
|
birthdayBlock.Height)
|
|
}
|
|
})
|
|
if !success {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestLabelTransaction tests labelling of transactions with invalid labels,
|
|
// and failure to label a transaction when it already has a label.
|
|
func TestLabelTransaction(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
|
|
// Whether the transaction should be known to the wallet.
|
|
txKnown bool
|
|
|
|
// Whether the test should write an existing label to disk.
|
|
existingLabel bool
|
|
|
|
// The overwrite parameter to call label transaction with.
|
|
overwrite bool
|
|
|
|
// The error we expect to be returned.
|
|
expectedErr error
|
|
}{
|
|
{
|
|
name: "existing label, not overwrite",
|
|
txKnown: true,
|
|
existingLabel: true,
|
|
overwrite: false,
|
|
expectedErr: ErrTxLabelExists,
|
|
},
|
|
{
|
|
name: "existing label, overwritten",
|
|
txKnown: true,
|
|
existingLabel: true,
|
|
overwrite: true,
|
|
expectedErr: nil,
|
|
},
|
|
{
|
|
name: "no prexisting label, ok",
|
|
txKnown: true,
|
|
existingLabel: false,
|
|
overwrite: false,
|
|
expectedErr: nil,
|
|
},
|
|
{
|
|
name: "transaction unknown",
|
|
txKnown: false,
|
|
existingLabel: false,
|
|
overwrite: false,
|
|
expectedErr: ErrUnknownTransaction,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
test := test
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
w, cleanup := testWallet(t)
|
|
defer cleanup()
|
|
|
|
// If the transaction should be known to the store, we
|
|
// write txdetail to disk.
|
|
if test.txKnown {
|
|
rec, err := wtxmgr.NewTxRecord(
|
|
TstSerializedTx, time.Now(),
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
err = walletdb.Update(w.db,
|
|
func(tx walletdb.ReadWriteTx) error {
|
|
|
|
ns := tx.ReadWriteBucket(
|
|
wtxmgrNamespaceKey,
|
|
)
|
|
|
|
return w.TxStore.InsertTx(
|
|
ns, rec, nil,
|
|
)
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("could not insert tx: %v", err)
|
|
}
|
|
}
|
|
|
|
// If we want to setup an existing label for the purpose
|
|
// of the test, write one to disk.
|
|
if test.existingLabel {
|
|
err := w.LabelTransaction(
|
|
*TstTxHash, "existing label", false,
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("could not write label: %v",
|
|
err)
|
|
}
|
|
}
|
|
|
|
newLabel := "new label"
|
|
err := w.LabelTransaction(
|
|
*TstTxHash, newLabel, test.overwrite,
|
|
)
|
|
if err != test.expectedErr {
|
|
t.Fatalf("expected: %v, got: %v",
|
|
test.expectedErr, err)
|
|
}
|
|
})
|
|
}
|
|
}
|