Skip to content
This repository has been archived by the owner on Apr 2, 2024. It is now read-only.

Commit

Permalink
Add block header socket processing
Browse files Browse the repository at this point in the history
  • Loading branch information
galt-tr committed Apr 16, 2022
1 parent e8f8377 commit e2ae232
Show file tree
Hide file tree
Showing 7 changed files with 299 additions and 344 deletions.
158 changes: 17 additions & 141 deletions action_blockheader.go
Original file line number Diff line number Diff line change
@@ -1,170 +1,46 @@
package bux

// RecordTransaction will parse the transaction and Save it into the Datastore
//
// Internal (known) transactions: there is a corresponding `draft_transaction` via `draft_id`
// External (known) transactions: there are output(s) related to the destination `reference_id`, tx is valid (mempool/on-chain)
// External (unknown) transactions: no reference id but some output(s) match known outputs, tx is valid (mempool/on-chain)
// Unknown transactions: no matching outputs, tx will be disregarded
import (
"context"

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

// RecordBlockheader will Save a block header into the Datastore
//
// xPubKey is the raw public xPub
// txHex is the raw transaction hex
// draftID is the unique draft id from a previously started New() transaction (draft_transaction.ID)
// hash is the hash of the block header
// bh is the block header data
// opts are model options and can include "metadata"
/*func (c *Client) RecordBlockHeader(ctx context.Context, hash string, bh bc.BlockHeader,
opts ...ModelOps) (*Transaction, error) {
func (c *Client) RecordBlockHeader(ctx context.Context, hash string, bh bc.BlockHeader,
opts ...ModelOps) (*BlockHeader, error) {

// Check for existing NewRelic transaction
ctx = c.GetOrStartTxn(ctx, "record_blockheader")

// Create the model & set the default options (gives options from client->model)
newOpts := c.DefaultModelOptions(append(opts, New())...)
transaction := newTransactionWithDraftID(
txHex, draftID, newOpts...,
)
blockHeader := newBlockHeader(hash, bh, newOpts...)

// Ensure that we have a transaction id (created from the txHex)
id := transaction.GetID()
id := blockHeader.GetID()
if len(id) == 0 {
return nil, ErrMissingTxHex
return nil, ErrMissingBlockHeaderHash
}

// Create the lock and set the release for after the function completes
unlock, err := newWriteLock(
ctx, "action-record-transaction-"+id, c.Cachestore(),
ctx, "action-record-block-header-"+id, c.Cachestore(),
)
defer unlock()
if err != nil {
return nil, err
}

// OPTION: check incoming transactions (if enabled, will add to queue for checking on-chain)
if !c.IsITCEnabled() {
transaction.DebugLog("incoming transaction check is disabled")
} else {
// Incoming (external/unknown) transaction (no draft id was given)
if len(transaction.DraftID) == 0 {
// Process & save the model
incomingTx := newIncomingTransaction(
transaction.ID, txHex, newOpts...,
)
if err = incomingTx.Save(ctx); err != nil {
return nil, err
}
// Added to queue
return newTransactionFromIncomingTransaction(incomingTx), nil
}
// Internal tx (must match draft tx)
if transaction.draftTransaction, err = getDraftTransactionID(
ctx, transaction.xPubID, transaction.DraftID,
transaction.GetOptions(false)...,
); err != nil {
return nil, err
} else if transaction.draftTransaction == nil {
return nil, ErrDraftNotFound
}
}
// Process & save the transaction model
if err = transaction.Save(ctx); err != nil {
if err = blockHeader.Save(ctx); err != nil {
return nil, err
}

// Return the response
return transaction, nil
}
// NewTransaction will create a new draft transaction and return it
//
// ctx is the context
// rawXpubKey is the raw xPub key
// config is the TransactionConfig
// metadata is added to the model
// opts are additional model options to be applied
func (c *Client) NewTransaction(ctx context.Context, rawXpubKey string, config *TransactionConfig,
opts ...ModelOps) (*DraftTransaction, error) {
// Check for existing NewRelic draftTransaction
ctx = c.GetOrStartTxn(ctx, "new_transaction")
// Create the lock and set the release for after the function completes
unlock, err := newWaitWriteLock(
ctx, "action-xpub-"+utils.Hash(rawXpubKey), c.Cachestore(),
)
defer unlock()
if err != nil {
return nil, err
}
// todo: this needs adjusting via Chainstate or mAPI
if config.FeeUnit == nil {
config.FeeUnit = c.GetFeeUnit(ctx, "miner")
}
// Create the model & set the default options (gives options from client->model)
draftTransaction := newDraftTransaction(
rawXpubKey, config,
c.DefaultModelOptions(append(opts, New())...)...,
)
// Save the model
if err = draftTransaction.Save(ctx); err != nil {
return nil, err
}
// Return the created model
return draftTransaction, nil
}
// GetTransaction will get a transaction from the Datastore
//
// ctx is the context
// testTxID is the transaction ID
func (c *Client) GetTransaction(ctx context.Context, xPubID, txID string) (*Transaction, error) {
// Check for existing NewRelic transaction
ctx = c.GetOrStartTxn(ctx, "get_transaction")
// Get the transaction by ID
transaction, err := getTransactionByID(
ctx, xPubID, txID, c.DefaultModelOptions()...,
)
if err != nil {
return nil, err
}
if transaction == nil {
return nil, ErrMissingTransaction
}
return transaction, nil
}
// GetTransactions will get all transactions for a given xpub from the Datastore
//
// ctx is the context
// rawXpubKey is the raw xPub key
// metadataConditions is added to the request for searching
// conditions is added the request for searching
func (c *Client) GetTransactions(ctx context.Context, xPubID string, metadataConditions *Metadata,
conditions *map[string]interface{}) ([]*Transaction, error) {
// Check for existing NewRelic transaction
ctx = c.GetOrStartTxn(ctx, "get_transaction")
// Get the transaction by ID
// todo: add params for: page size and page (right now it is unlimited)
transactions, err := getTransactionsByXpubID(
ctx, xPubID, metadataConditions, conditions, 0, 0,
c.DefaultModelOptions()...,
)
if err != nil {
return nil, err
}
return transactions, nil
return blockHeader, nil
}
*/
3 changes: 3 additions & 0 deletions chainstate/monitor_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package chainstate
import (
"context"

"github.com/libsv/go-bc"

"github.com/mrz1836/go-whatsonchain"
)

Expand All @@ -11,5 +13,6 @@ type MonitorHandler interface {
whatsonchain.SocketHandler
SetMonitor(monitor *Monitor)
RecordTransaction(ctx context.Context, txHex string) error
RecordBlockHeader(ctx context.Context, bh bc.BlockHeader) error
GetWhatsOnChain() whatsonchain.ClientInterface
}
2 changes: 1 addition & 1 deletion client_internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func (c *Client) loadMonitor(ctx context.Context) (err error) {
// Load monitor if set by the user
monitor := c.options.chainstate.Monitor()
if monitor != nil {
handler := NewTransactionMonitorHandler(ctx, c, monitor)
handler := NewMonitorHandler(ctx, c, monitor)
err = c.loadMonitoredDestinations(ctx, monitor)
if err != nil {
return
Expand Down
3 changes: 3 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ var ErrDraftIDMismatch = errors.New("transaction draft id does not match utxo dr
// ErrMissingTxHex is when the hex is missing or invalid and creates an empty id
var ErrMissingTxHex = errors.New("transaction hex is empty or id is missing")

// ErrMissingBlockHeaderHash is when the hash is missing or invalid and creates an empty id
var ErrMissingBlockHeaderHash = errors.New("block header hash is empty or id is missing")

// ErrUtxoAlreadySpent is when the utxo is already spent, but is trying to be used
var ErrUtxoAlreadySpent = errors.New("utxo has already been spent")

Expand Down
8 changes: 8 additions & 0 deletions interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"net/http"
"time"

"github.com/libsv/go-bc"

"github.com/BuxOrg/bux/cachestore"
"github.com/BuxOrg/bux/chainstate"
"github.com/BuxOrg/bux/datastore"
Expand Down Expand Up @@ -35,6 +37,11 @@ type TransactionService interface {
UpdateTransactionMetadata(ctx context.Context, xPubID, id string, metadata Metadata) (*Transaction, error)
}

// BlockHeaderService is the block header actions
type BlockHeaderService interface {
RecordBlockHeader(ctx context.Context, hash string, bh bc.BlockHeader, opts ...ModelOps) (*BlockHeader, error)
}

// DestinationService is the destination actions
type DestinationService interface {
GetDestinationByID(ctx context.Context, xPubID, id string) (*Destination, error)
Expand Down Expand Up @@ -96,6 +103,7 @@ type ClientInterface interface {
DestinationService
PaymailService
TransactionService
BlockHeaderService
UTXOService
XPubService
AddModels(ctx context.Context, autoMigrate bool, models ...interface{}) error
Expand Down
Loading

0 comments on commit e2ae232

Please sign in to comment.