Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions backend/devices/bitbox02/keystore_simulator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ import (
"bufio"
"bytes"
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"encoding/json"
"fmt"
"hash"
"io"
"net"
"net/http"
Expand All @@ -39,11 +41,13 @@ import (
"testing"
"time"

"github.com/BitBoxSwiss/bitbox-wallet-app/backend/accounts"
"github.com/BitBoxSwiss/bitbox-wallet-app/backend/coins/btc"
"github.com/BitBoxSwiss/bitbox-wallet-app/backend/coins/btc/addresses"
"github.com/BitBoxSwiss/bitbox-wallet-app/backend/coins/btc/blockchain"
"github.com/BitBoxSwiss/bitbox-wallet-app/backend/coins/btc/maketx"
"github.com/BitBoxSwiss/bitbox-wallet-app/backend/coins/btc/types"
"github.com/BitBoxSwiss/bitbox-wallet-app/backend/coins/btc/util"
coinpkg "github.com/BitBoxSwiss/bitbox-wallet-app/backend/coins/coin"
"github.com/BitBoxSwiss/bitbox-wallet-app/backend/coins/eth"
"github.com/BitBoxSwiss/bitbox-wallet-app/backend/coins/ltc"
Expand All @@ -59,11 +63,13 @@ import (
"github.com/BitBoxSwiss/bitbox02-api-go/api/firmware/mocks"
"github.com/BitBoxSwiss/bitbox02-api-go/communication/u2fhid"
"github.com/BitBoxSwiss/bitbox02-api-go/util/semver"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/btcutil/hdkeychain"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -698,3 +704,122 @@ func TestSimulatorVerifyAddressETH(t *testing.T) {
}
})
}

func computePaymentRequestSighash(paymentRequest *accounts.PaymentRequest, slip44 uint32, outputValue uint64, outputAddress string) ([]byte, error) {

hashDataLenPrefixed := func(hasher hash.Hash, data []byte) {
_ = wire.WriteVarInt(hasher, 0, uint64(len(data)))
hasher.Write(data)
}

sighash := sha256.New()

// versionMagic
sighash.Write([]byte("SL\x00\x24"))

// nonce
hashDataLenPrefixed(sighash, paymentRequest.Nonce)

// recipientName
hashDataLenPrefixed(sighash, []byte(paymentRequest.RecipientName))

// memos
_ = wire.WriteVarInt(sighash, 0, uint64(len(paymentRequest.Memos)))
for _, textMemo := range paymentRequest.Memos {
_ = binary.Write(sighash, binary.LittleEndian, uint32(1))
hashDataLenPrefixed(sighash, []byte(textMemo.Note))
}

// coinType
_ = binary.Write(sighash, binary.LittleEndian, slip44)

// outputsHash (only one output for now)
outputHasher := sha256.New()
_ = binary.Write(outputHasher, binary.LittleEndian, outputValue)
hashDataLenPrefixed(outputHasher, []byte(outputAddress))
sighash.Write(outputHasher.Sum(nil))

return sighash.Sum(nil), nil
}

func TestSimulatorSignBTCPaymentRequest(t *testing.T) {
testInitializedSimulators(t, func(t *testing.T, device *Device, stdOut *bytes.Buffer) {
t.Helper()

if !device.Version().AtLeast(semver.NewSemVer(9, 24, 0)) {
// While payment requests were added in v9.19.0, the simulator only enabled the
// test merchant in v9.24.0.
t.Skip()
}

address, err := btcutil.DecodeAddress(
"bc1q2q0j6gmfxynj40p0kxsr9jkagcvgpuqv2zgq8j",
&chaincfg.MainNetParams)
require.NoError(t, err)
pkScript, err := util.PkScriptFromAddress(address)
require.NoError(t, err)
proposedTransaction := makeTx(t, device, maketx.NewOutputInfo(pkScript))

txProposal := proposedTransaction.TXProposal
recipientOutput := txProposal.Transaction.TxOut[txProposal.OutIndex]
value := uint64(recipientOutput.Value)

paymentRequest := &accounts.PaymentRequest{
RecipientName: "Test Merchant", // Hard-coded test merchant in simulator
Nonce: nil,
TotalAmount: value,
Memos: []accounts.TextMemo{
{
Note: "TextMemo line1\nTextMemo line2",
},
},
}

// Sign the payment request.
sighash, err := computePaymentRequestSighash(paymentRequest, 0, value, address.String())
require.NoError(t, err)
privKey, _ := btcec.PrivKeyFromBytes([]byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
require.NoError(t, err)
signature := ecdsa.SignCompact(privKey, sighash, true)
paymentRequest.Signature = signature[1:]

proposedTransaction.TXProposal.PaymentRequest = paymentRequest

require.NoError(t, device.Keystore().SignTransaction(proposedTransaction))
require.NoError(t, proposedTransaction.Finalize())
require.NoError(
t,
btc.TxValidityCheck(
proposedTransaction.TXProposal.Transaction,
proposedTransaction.TXProposal.PreviousOutputs,
proposedTransaction.TXProposal.SigHashes()))

const expected1 = `CONFIRM TRANSACTION ADDRESS SCREEN START
AMOUNT: 2.50000000 BTC
ADDRESS: Test Merchant
CONFIRM TRANSACTION ADDRESS SCREEN END`

const expected2 = `BODY: Memo from
Test Merchant
CONFIRM SCREEN END
CONFIRM SCREEN START
TITLE: Memo 1/2
BODY: TextMemo line1
CONFIRM SCREEN END
CONFIRM SCREEN START
TITLE: Memo 2/2
BODY: TextMemo line2
CONFIRM SCREEN END`

require.Eventually(t,
func() bool {
return strings.Contains(
stdOut.String(), expected1) &&
strings.Contains(
stdOut.String(), expected2) &&
!strings.Contains(stdOut.String(), address.String())
},
time.Second, 10*time.Millisecond)
})
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/btcsuite/btcd/btcec/v2 v2.3.4
github.com/btcsuite/btcd/btcutil v1.1.6
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0
github.com/ethereum/go-ethereum v1.14.13
github.com/flynn/noise v1.1.0
github.com/gorilla/mux v1.8.1
Expand Down Expand Up @@ -39,7 +40,6 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/ethereum/c-kzg-4844 v1.0.3 // indirect
github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
Expand Down