Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(SPV-937): upgrade to go-sdk #110

Merged
merged 13 commits into from
Sep 23, 2024
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
31 changes: 16 additions & 15 deletions beef/beef_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import (
"errors"
"fmt"

"github.com/libsv/go-bt/v2"
sdk "github.com/bitcoin-sv/go-sdk/transaction"
util "github.com/bitcoin-sv/go-sdk/util"
)

const (
Expand All @@ -26,8 +27,8 @@ const (
)

type TxData struct {
Transaction *bt.Tx
BumpIndex *bt.VarInt
Transaction *sdk.Transaction
BumpIndex *sdk.VarInt

txID string
}
Expand All @@ -38,7 +39,7 @@ func (td *TxData) Unmined() bool {

func (td *TxData) GetTxID() string {
if len(td.txID) == 0 {
td.txID = td.Transaction.TxID()
td.txID = td.Transaction.TxID().String()
}

return td.txID
Expand Down Expand Up @@ -71,7 +72,7 @@ func DecodeBEEF(beefHex string) (*DecodedBEEF, error) {
}, nil
}

func (d *DecodedBEEF) GetLatestTx() *bt.Tx {
func (d *DecodedBEEF) GetLatestTx() *sdk.Transaction {
return d.Transactions[len(d.Transactions)-1].Transaction // get the last transaction as the processed transaction - it should be the last one because of khan's ordering
}

Expand All @@ -80,7 +81,7 @@ func decodeBUMPs(beefBytes []byte) ([]*BUMP, []byte, error) {
return nil, nil, errors.New("cannot decode BUMP - no bytes provided")
}

nBump, bytesUsed := bt.NewVarIntFromBytes(beefBytes)
nBump, bytesUsed := sdk.NewVarIntFromBytes(beefBytes)

if nBump == 0 {
return nil, nil, errors.New("invalid BEEF- lack of BUMPs")
Expand All @@ -93,7 +94,7 @@ func decodeBUMPs(beefBytes []byte) ([]*BUMP, []byte, error) {
if len(beefBytes) == 0 {
return nil, nil, errors.New("insufficient bytes to extract BUMP blockHeight")
}
blockHeight, bytesUsed := bt.NewVarIntFromBytes(beefBytes)
blockHeight, bytesUsed := sdk.NewVarIntFromBytes(beefBytes)
beefBytes = beefBytes[bytesUsed:]

treeHeight := beefBytes[0]
Expand Down Expand Up @@ -126,7 +127,7 @@ func decodeBUMPPathsFromStream(treeHeight int, hexBytes []byte) ([][]BUMPLeaf, [
if len(hexBytes) == 0 {
return nil, nil, errors.New("cannot decode BUMP paths number of leaves from stream - no bytes provided")
}
nLeaves, bytesUsed := bt.NewVarIntFromBytes(hexBytes)
nLeaves, bytesUsed := sdk.NewVarIntFromBytes(hexBytes)
hexBytes = hexBytes[bytesUsed:]
bumpPath, remainingBytes, err := decodeBUMPLevel(nLeaves, hexBytes)
if err != nil {
Expand All @@ -139,14 +140,14 @@ func decodeBUMPPathsFromStream(treeHeight int, hexBytes []byte) ([][]BUMPLeaf, [
return bumpPaths, hexBytes, nil
}

func decodeBUMPLevel(nLeaves bt.VarInt, hexBytes []byte) ([]BUMPLeaf, []byte, error) {
func decodeBUMPLevel(nLeaves sdk.VarInt, hexBytes []byte) ([]BUMPLeaf, []byte, error) {
bumpPath := make([]BUMPLeaf, 0)
for i := 0; i < int(nLeaves); i++ {
if len(hexBytes) == 0 {
return nil, nil, fmt.Errorf("insufficient bytes to extract offset for %d leaf of %d leaves", i, int(nLeaves))
}

offset, bytesUsed := bt.NewVarIntFromBytes(hexBytes)
offset, bytesUsed := sdk.NewVarIntFromBytes(hexBytes)
hexBytes = hexBytes[bytesUsed:]

if len(hexBytes) == 0 {
Expand All @@ -173,7 +174,7 @@ func decodeBUMPLevel(nLeaves bt.VarInt, hexBytes []byte) ([]BUMPLeaf, []byte, er
return nil, nil, errors.New("insufficient bytes to extract hash of path")
}

hash := hex.EncodeToString(bt.ReverseBytes(hexBytes[:hashBytesCount]))
hash := hex.EncodeToString(util.ReverseBytes(hexBytes[:hashBytesCount]))
hexBytes = hexBytes[hashBytesCount:]

bumpLeaf := BUMPLeaf{
Expand All @@ -190,7 +191,7 @@ func decodeBUMPLevel(nLeaves bt.VarInt, hexBytes []byte) ([]BUMPLeaf, []byte, er
}

func decodeTransactionsWithPathIndexes(bytes []byte) ([]*TxData, error) {
nTransactions, offset := bt.NewVarIntFromBytes(bytes)
nTransactions, offset := sdk.NewVarIntFromBytes(bytes)

if nTransactions < 2 {
return nil, errors.New("invalid BEEF- not enough transactions provided to decode BEEF")
Expand All @@ -201,16 +202,16 @@ func decodeTransactionsWithPathIndexes(bytes []byte) ([]*TxData, error) {
transactions := make([]*TxData, 0, int(nTransactions))

for i := 0; i < int(nTransactions); i++ {
tx, offset, err := bt.NewTxFromStream(bytes)
tx, offset, err := sdk.NewTransactionFromStream(bytes)
if err != nil {
return nil, err
}
bytes = bytes[offset:]

var pathIndex *bt.VarInt
var pathIndex *sdk.VarInt

if bytes[0] == HasBump {
value, offset := bt.NewVarIntFromBytes(bytes[1:])
value, offset := sdk.NewVarIntFromBytes(bytes[1:])
pathIndex = &value
bytes = bytes[1+offset:]
} else if bytes[0] == HasNoBump {
Expand Down
41 changes: 20 additions & 21 deletions beef/beef_tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@ import (
"errors"
"testing"

"github.com/libsv/go-bt/v2"
"github.com/libsv/go-bt/v2/bscript"
"github.com/stretchr/testify/assert"

script "github.com/bitcoin-sv/go-sdk/script"
sdk "github.com/bitcoin-sv/go-sdk/transaction"
)

func TestDecodeBEEF_DecodeBEEF_HappyPaths(t *testing.T) {
testCases := []struct {
name string
hexStream string
expectedDecodedBEEF *DecodedBEEF
pathIndexForTheOldestInput *bt.VarInt
pathIndexForTheOldestInput *sdk.VarInt
}{
{
name: "valid BEEF with 1 BUMP and 1 input transaction",
Expand Down Expand Up @@ -51,51 +52,49 @@ func TestDecodeBEEF_DecodeBEEF_HappyPaths(t *testing.T) {
},
Transactions: []*TxData{
{
Transaction: &bt.Tx{
Transaction: &sdk.Transaction{
Version: 1,
LockTime: 0,
Inputs: []*bt.Input{
Inputs: []*sdk.TransactionInput{
{
PreviousTxSatoshis: 0,
PreviousTxOutIndex: 1,
SequenceNumber: 4294967295,
PreviousTxScript: nil,
SourceTxOutIndex: 1,
SequenceNumber: 4294967295,
UnlockingScriptTemplate: nil,
},
},
Outputs: []*bt.Output{
Outputs: []*sdk.TransactionOutput{
{
Satoshis: 26174,
LockingScript: bscript.NewFromBytes([]byte("76a9146bfd5c7fbe21529d45803dbcf0c87dd3c71efbc288ac")),
LockingScript: script.NewFromBytes([]byte("76a9146bfd5c7fbe21529d45803dbcf0c87dd3c71efbc288ac")),
},
},
},
BumpIndex: func(v bt.VarInt) *bt.VarInt { return &v }(0x0),
BumpIndex: func(v sdk.VarInt) *sdk.VarInt { return &v }(0x0),
},

{
Transaction: &bt.Tx{
Transaction: &sdk.Transaction{
Version: 1,
LockTime: 0,
Inputs: []*bt.Input{
Inputs: []*sdk.TransactionInput{
{
PreviousTxSatoshis: 0,
PreviousTxOutIndex: 0,
SequenceNumber: 4294967295,
PreviousTxScript: nil,
SourceTxOutIndex: 0,
SequenceNumber: 4294967295,
UnlockingScriptTemplate: nil,
},
},
Outputs: []*bt.Output{
Outputs: []*sdk.TransactionOutput{
{
Satoshis: 26172,
LockingScript: bscript.NewFromBytes([]byte("76a9146bfd5c7fbe21529d45803dbcf0c87dd3c71efbc288ac")),
LockingScript: script.NewFromBytes([]byte("76a9146bfd5c7fbe21529d45803dbcf0c87dd3c71efbc288ac")),
},
},
},
BumpIndex: nil,
},
},
},
pathIndexForTheOldestInput: func(v bt.VarInt) *bt.VarInt { return &v }(0x0),
pathIndexForTheOldestInput: func(v sdk.VarInt) *sdk.VarInt { return &v }(0x0),
},
}
for _, tc := range testCases {
Expand Down
4 changes: 1 addition & 3 deletions beef/bump.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package beef

import (
"errors"

"github.com/libsv/go-bc"
)

// BUMPs represents a slice of BUMPs - BSV Unified Merkle Paths
Expand Down Expand Up @@ -66,8 +64,8 @@ func calculateMerkleRoot(baseLeaf BUMPLeaf, bump BUMP) (string, error) {
}

leftNode, rightNode := prepareNodes(baseLeaf, offset, *leafInPair, newOffset)
str, err := merkleTreeParentStr(leftNode, rightNode)

wregulski marked this conversation as resolved.
Show resolved Hide resolved
str, err := bc.MerkleTreeParentStr(leftNode, rightNode)
if err != nil {
return "", err
}
Expand Down
43 changes: 43 additions & 0 deletions beef/merkletree.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package beef

import (
"encoding/hex"

crypto "github.com/bitcoin-sv/go-sdk/primitives/hash"
"github.com/bitcoin-sv/go-sdk/util"
)

// INFO: This function is moved to go-paymail from go-bc
// https://github.com/libsv/go-bc/blob/master/merkletreeparent.go
// try to use go-sdk implementation when available

// merkleTreeParentStr returns the Merkle Tree parent of two Merkle
// Tree children using hex strings instead of just bytes.
func merkleTreeParentStr(leftNode, rightNode string) (string, error) {
l, err := hex.DecodeString(leftNode)
if err != nil {
return "", err
}
r, err := hex.DecodeString(rightNode)
if err != nil {
return "", err
}

return hex.EncodeToString(merkleTreeParent(l, r)), nil
}

// merkleTreeParent returns the Merkle Tree parent of two Merkle tree children.
func merkleTreeParent(leftNode, rightNode []byte) []byte {
// swap endianness before concatenating
l := util.ReverseBytes(leftNode)
r := util.ReverseBytes(rightNode)

// concatenate leaves
concat := append(l, r...)
chris-4chain marked this conversation as resolved.
Show resolved Hide resolved

// hash the concatenation
hash := crypto.Sha256d(concat)

// swap endianness at the end and convert to hex string
return util.ReverseBytes(hash)
}
1 change: 0 additions & 1 deletion dns_sec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (

// TestClient_CheckDNSSEC will test the method CheckDNSSEC()
func TestClient_CheckDNSSEC(t *testing.T) {

// t.Parallel() (turned off - race condition)

// Integration test (requires internet connection)
Expand Down
5 changes: 3 additions & 2 deletions examples/client/p2p_send_transaction/p2p_send_transaction.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package main

import (
"github.com/bitcoin-sv/go-paymail"
"log"

"github.com/bitcoin-sv/go-paymail"
)

func main() {
Expand Down Expand Up @@ -41,7 +42,7 @@ func main() {
MetaData: &paymail.P2PMetaData{
Note: "Thanks for dinner Satchmo!",
Sender: "mrz@moneybutton.com",
PubKey: "insert-pubkey-for-sender", // todo: replace with a real pubkey for the Sender
PublicKey: "insert-pubkey-for-sender", // todo: replace with a real pubkey for the Sender
Signature: "insert-signature-if-txid", // todo: replace with a real signature of the txid by the sender
},
Reference: destination.Reference,
Expand Down
54 changes: 28 additions & 26 deletions examples/server/run_server/demo_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@ import (
"encoding/hex"
"errors"
"fmt"
"github.com/bitcoin-sv/go-paymail/logging"
"strings"

"github.com/bitcoin-sv/go-paymail/logging"

"github.com/bitcoin-sv/go-paymail"
"github.com/bitcoinschema/go-bitcoin/v2"

bsm "github.com/bitcoin-sv/go-sdk/compat/bsm"
ec "github.com/bitcoin-sv/go-sdk/primitives/ec"
"github.com/bitcoin-sv/go-sdk/script"
"github.com/bitcoin-sv/go-sdk/transaction/template/p2pkh"
)

// paymailAddressTable is the demo data for the example server (table: paymail_address)
Expand Down Expand Up @@ -64,24 +69,20 @@ func generateDemoPaymail(alias, domain, avatar, name, id string) (err error) {
}

// Generate new private key
if row.PrivateKey, err = bitcoin.CreatePrivateKeyString(); err != nil {
key, err := ec.NewPrivateKey()
if err != nil {
return
}

// Get address
if row.LastAddress, err = bitcoin.GetAddressFromPrivateKeyString(
row.PrivateKey, true,
); err != nil {
return
}
row.PrivateKey = hex.EncodeToString((key.Serialize()))

// Derive a pubkey from private key
if row.PubKey, err = bitcoin.PubKeyFromPrivateKeyString(
row.PrivateKey, true,
); err != nil {
addr, err := script.NewAddressFromPublicKey(key.PubKey(), true)
if err != nil {
return
}

row.LastAddress = addr.AddressString

// Add to the table
demoPaymailAddressTable = append(demoPaymailAddressTable, row)

Expand Down Expand Up @@ -112,19 +113,23 @@ func DemoCreateAddressResolutionResponse(_ context.Context, alias, domain string
response := &paymail.ResolutionPayload{}

// Generate the script
if response.Output, err = bitcoin.ScriptFromAddress(
p.LastAddress,
); err != nil {
return nil, errors.New("error generating script: " + err.Error())
sc, _ := script.NewAddressFromString(p.LastAddress)
ls, _ := p2pkh.Lock(sc)

response.Output = ls.String()

privateKeyFromHex, err := ec.PrivateKeyFromHex(p.PrivateKey)
if err != nil {
return nil, errors.New("unable to decode private key: " + err.Error())
}

// Create a signature of output if senderValidation is enabled
if senderValidation {
if response.Signature, err = bitcoin.SignMessage(
p.PrivateKey, response.Output, false,
); err != nil {
sigBytes, err := bsm.SignMessage(privateKeyFromHex, ls.Bytes())
if err != nil {
return nil, errors.New("invalid signature: " + err.Error())
}
response.Signature = paymail.EncodeSignature(sigBytes)
}

return response, nil
Expand All @@ -145,12 +150,9 @@ func DemoCreateP2PDestinationResponse(_ context.Context, alias, domain string,
Satoshis: satoshis,
}

// Generate the script
if output.Script, err = bitcoin.ScriptFromAddress(
p.LastAddress,
); err != nil {
return nil, err
}
sc, _ := script.NewAddressFromString(p.LastAddress)
ls, _ := p2pkh.Lock(sc)
output.Script = ls.String()

// Create the response
return &paymail.PaymentDestinationPayload{
Expand Down
Loading