diff --git a/go.mod b/go.mod index 1eaa031c..0e485b98 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/99designs/gqlgen v0.17.40 github.com/DATA-DOG/go-sqlmock v1.5.0 github.com/bitcoin-sv/go-broadcast-client v0.9.0 - github.com/bitcoin-sv/go-paymail v0.9.1 + github.com/bitcoin-sv/go-paymail v0.9.2 github.com/bitcoinschema/go-bitcoin/v2 v2.0.5 github.com/bitcoinschema/go-map v0.1.0 github.com/centrifugal/centrifuge-go v0.10.2 diff --git a/go.sum b/go.sum index 38aee447..f8156d09 100644 --- a/go.sum +++ b/go.sum @@ -57,6 +57,8 @@ github.com/bitcoin-sv/go-broadcast-client v0.9.0 h1:6oR1th7TppFtWxcfCHFvEM0XnwTv github.com/bitcoin-sv/go-broadcast-client v0.9.0/go.mod h1:hami7qUkK0eoZolDXeo4tOLD16qbDXuZRV7BQ1RDzaE= github.com/bitcoin-sv/go-paymail v0.9.1 h1:8oUX9uoWGiQ8VrwzDa8AIQk4rUxb59+JdaBbnvQYSMY= github.com/bitcoin-sv/go-paymail v0.9.1/go.mod h1:i0mTFBj3hfKEZ1tJUgUfV38b3jJVFgyeIBGR0c9lqOI= +github.com/bitcoin-sv/go-paymail v0.9.2 h1:41hWOn3N3tpOPh0VZN7wsb+8OhvFzNJSaWTkCJW/vjE= +github.com/bitcoin-sv/go-paymail v0.9.2/go.mod h1:i0mTFBj3hfKEZ1tJUgUfV38b3jJVFgyeIBGR0c9lqOI= github.com/bitcoinschema/go-bitcoin/v2 v2.0.5 h1:Sgh5Eb746Zck/46rFDrZZEXZWyO53fMuWYhNoZa1tck= github.com/bitcoinschema/go-bitcoin/v2 v2.0.5/go.mod h1:JjO1ivfZv6vhK0uAXzyH08AAHlzNMAfnyK1Fiv9r4ZA= github.com/bitcoinschema/go-bob v0.4.0 h1:adsAEboLQCg0D6e9vwcJUJEJScszsouAYCYu35UAiGo= diff --git a/paymail_service_provider.go b/paymail_service_provider.go index db4992d3..b9cecc4e 100644 --- a/paymail_service_provider.go +++ b/paymail_service_provider.go @@ -5,11 +5,11 @@ import ( "database/sql" "encoding/hex" "fmt" - "github.com/bitcoin-sv/go-paymail/beef" "reflect" "time" "github.com/bitcoin-sv/go-paymail" + "github.com/bitcoin-sv/go-paymail/beef" "github.com/bitcoin-sv/go-paymail/server" "github.com/bitcoin-sv/go-paymail/spv" "github.com/bitcoinschema/go-bitcoin/v2" @@ -175,15 +175,12 @@ func (p *PaymailDefaultServiceProvider) RecordTransaction(ctx context.Context, return nil, err } - if p2pTx.DecodedBeef == nil { - return &paymail.P2PTransactionPayload{ - Note: p2pTx.MetaData.Note, - TxID: transaction.ID, - }, nil + if p2pTx.DecodedBeef != nil { + if reflect.TypeOf(rts) == reflect.TypeOf(&externalIncomingTx{}) { + go saveBEEFTxInputs(ctx, p.client, p2pTx.DecodedBeef) + } } - go saveBEEFTxInputs(ctx, p.client, p2pTx, rts) - // Return the response from the p2p request return &paymail.P2PTransactionPayload{ Note: p2pTx.MetaData.Note, @@ -318,59 +315,32 @@ func deriveKey(rawXPubKey string, num uint32) (k *derivedPubKey, err error) { return } -func saveBEEFTxInputs(ctx context.Context, c ClientInterface, p2pTx *paymail.P2PTransaction, rts recordIncomingTxStrategy) { - if reflect.TypeOf(rts) != reflect.TypeOf(&externalIncomingTx{}) { - return - } - - inputsToAdd, err := getInputsWhichAreNotInDb(c, p2pTx) +func saveBEEFTxInputs(ctx context.Context, c ClientInterface, dBeef *beef.DecodedBEEF) { + inputsToAdd, err := getInputsWhichAreNotInDb(c, dBeef) if err != nil { c.Logger().Error(ctx, "error in saveBEEFTxInputs", err) } for _, input := range inputsToAdd { - bump, err := getBump(p2pTx, input) - if err != nil { - c.Logger().Error(ctx, fmt.Errorf("error in saveBEEFTxInputs: %w for beef: %v", err, p2pTx.DecodedBeef).Error()) + var bump *BUMP + if input.BumpIndex != nil { // mined + bump, err = getBump(int(*input.BumpIndex), dBeef.BUMPs) + if err != nil { + c.Logger().Error(ctx, fmt.Errorf("error in saveBEEFTxInputs: %w for beef: %v", err, dBeef).Error()) + } + } + err = saveBeefTransactionInput(ctx, c, input, bump) if err != nil { - c.Logger().Error(ctx, fmt.Errorf("error in saveBEEFTxInputs: %w for beef: %v", err, p2pTx.DecodedBeef).Error()) - } - } - -} - -func getBump(p2pTx *paymail.P2PTransaction, input *beef.TxData) (*BUMP, error) { - bumpIndex := uint(input.BumpIndex.Length()) - if bumpIndex > uint(len(p2pTx.DecodedBeef.BUMPs)) { - return nil, fmt.Errorf("error in getBump: bump index exceeds bumps length") - } - bump := p2pTx.DecodedBeef.BUMPs[bumpIndex] - paths := make([][]BUMPLeaf, 0) - - for _, path := range bump.Path { - pathLeaves := make([]BUMPLeaf, 0) - for _, leaf := range path { - l := BUMPLeaf{ - Offset: leaf.Offset, - Hash: leaf.Hash, - TxID: leaf.TxId, - Duplicate: leaf.Duplicate, - } - pathLeaves = append(pathLeaves, l) + c.Logger().Error(ctx, fmt.Errorf("error in saveBEEFTxInputs: %w for beef: %v", err, dBeef).Error()) } - paths = append(paths, pathLeaves) } - return &BUMP{ - BlockHeight: bump.BlockHeight, - Path: paths, - }, nil } -func getInputsWhichAreNotInDb(c ClientInterface, p2pTx *paymail.P2PTransaction) ([]*beef.TxData, error) { +func getInputsWhichAreNotInDb(c ClientInterface, dBeef *beef.DecodedBEEF) ([]*beef.TxData, error) { var txIDs []string - for _, tx := range p2pTx.DecodedBeef.Transactions { + for _, tx := range dBeef.Transactions { txIDs = append(txIDs, tx.GetTxID()) } dbTxs, err := c.GetTransactionsByIDs(context.Background(), txIDs) @@ -384,7 +354,7 @@ func getInputsWhichAreNotInDb(c ClientInterface, p2pTx *paymail.P2PTransaction) return txs, nil } - for _, input := range p2pTx.DecodedBeef.Transactions { + for _, input := range dBeef.Transactions { found := false for _, dbTx := range dbTxs { if dbTx.GetID() == input.GetTxID() { @@ -400,6 +370,34 @@ func getInputsWhichAreNotInDb(c ClientInterface, p2pTx *paymail.P2PTransaction) return txs, nil } +func getBump(bumpIndx int, bumps beef.BUMPs) (*BUMP, error) { + if bumpIndx > len(bumps) { + return nil, fmt.Errorf("error in getBump: bump index exceeds bumps length") + } + + bump := bumps[bumpIndx] + paths := make([][]BUMPLeaf, 0) + + for _, path := range bump.Path { + pathLeaves := make([]BUMPLeaf, 0) + for _, leaf := range path { + l := BUMPLeaf{ + Offset: leaf.Offset, + Hash: leaf.Hash, + TxID: leaf.TxId, + Duplicate: leaf.Duplicate, + } + pathLeaves = append(pathLeaves, l) + } + paths = append(paths, pathLeaves) + } + + return &BUMP{ + BlockHeight: bump.BlockHeight, + Path: paths, + }, nil +} + func saveBeefTransactionInput(ctx context.Context, c ClientInterface, input *beef.TxData, bump *BUMP) error { newOpts := c.DefaultModelOptions(New()) inputTx := newTransaction(input.Transaction.String(), newOpts...) @@ -422,7 +420,7 @@ func saveBeefTransactionInput(ctx context.Context, c ClientInterface, input *bee err := inputTx.Save(ctx) if err != nil { - return fmt.Errorf("error in saveBeefTransactionInput during saving tx: %s", err.Error()) + return fmt.Errorf("error in saveBeefTransactionInput during saving tx: %w", err) } return nil }