perf: scriptpublickey in mempool, no txscript.

This commit is contained in:
D-Stacks 2022-07-10 15:47:23 +02:00
parent 5b9a5374f6
commit 79c934e39c
9 changed files with 53 additions and 89 deletions

View File

@ -5,6 +5,7 @@ import (
"github.com/kaspanet/kaspad/domain/dagconfig" "github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript" "github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
"github.com/kaspanet/kaspad/app/appmessage" "github.com/kaspanet/kaspad/app/appmessage"
@ -421,7 +422,7 @@ func (nl *NotificationListener) convertUTXOChangesToUTXOsChangedNotification(
} }
func (nl *NotificationListener) scriptPubKeyStringToAddressString(scriptPublicKeyString utxoindex.ScriptPublicKeyString) (string, error) { func (nl *NotificationListener) scriptPubKeyStringToAddressString(scriptPublicKeyString utxoindex.ScriptPublicKeyString) (string, error) {
scriptPubKey := utxoindex.ConvertStringToScriptPublicKey(scriptPublicKeyString) scriptPubKey := externalapi.NewScriptPublicKeyFromString(string(scriptPublicKeyString))
// ignore error because it is often returned when the script is of unknown type // ignore error because it is often returned when the script is of unknown type
scriptType, address, err := txscript.ExtractScriptPubKeyAddress(scriptPubKey, nl.params) scriptType, address, err := txscript.ExtractScriptPubKeyAddress(scriptPubKey, nl.params)

View File

@ -32,22 +32,6 @@ func ConvertUTXOOutpointEntryPairsToUTXOsByAddressesEntries(address string, pair
return utxosByAddressesEntries return utxosByAddressesEntries
} }
// convertUTXOOutpointsToUTXOsByAddressesEntries converts
// UTXOOutpoints to a slice of UTXOsByAddressesEntry
func convertUTXOOutpointsToUTXOsByAddressesEntries(address string, outpoints utxoindex.UTXOOutpoints) []*appmessage.UTXOsByAddressesEntry {
utxosByAddressesEntries := make([]*appmessage.UTXOsByAddressesEntry, 0, len(outpoints))
for outpoint := range outpoints {
utxosByAddressesEntries = append(utxosByAddressesEntries, &appmessage.UTXOsByAddressesEntry{
Address: address,
Outpoint: &appmessage.RPCOutpoint{
TransactionID: outpoint.TransactionID.String(),
Index: outpoint.Index,
},
})
}
return utxosByAddressesEntries
}
// ConvertAddressStringsToUTXOsChangedNotificationAddresses converts address strings // ConvertAddressStringsToUTXOsChangedNotificationAddresses converts address strings
// to UTXOsChangedNotificationAddresses // to UTXOsChangedNotificationAddresses
func (ctx *Context) ConvertAddressStringsToUTXOsChangedNotificationAddresses( func (ctx *Context) ConvertAddressStringsToUTXOsChangedNotificationAddresses(
@ -63,7 +47,7 @@ func (ctx *Context) ConvertAddressStringsToUTXOsChangedNotificationAddresses(
if err != nil { if err != nil {
return nil, errors.Errorf("Could not create a scriptPublicKey for address '%s': %s", addressString, err) return nil, errors.Errorf("Could not create a scriptPublicKey for address '%s': %s", addressString, err)
} }
scriptPublicKeyString := utxoindex.ConvertScriptPublicKeyToString(scriptPublicKey) scriptPublicKeyString := utxoindex.ScriptPublicKeyString(scriptPublicKey.String())
addresses[i] = &UTXOsChangedNotificationAddress{ addresses[i] = &UTXOsChangedNotificationAddress{
Address: addressString, Address: addressString,
ScriptPublicKeyString: scriptPublicKeyString, ScriptPublicKeyString: scriptPublicKeyString,

View File

@ -3,6 +3,7 @@ package rpchandlers
import ( import (
"github.com/kaspanet/kaspad/app/appmessage" "github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/app/rpc/rpccontext" "github.com/kaspanet/kaspad/app/rpc/rpccontext"
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
"github.com/kaspanet/kaspad/util" "github.com/kaspanet/kaspad/util"
@ -32,9 +33,16 @@ func HandleGetMempoolEntriesByAddresses(context *rpccontext.Context, _ *router.R
sending := make([]*appmessage.MempoolEntry, 0) sending := make([]*appmessage.MempoolEntry, 0)
receiving := make([]*appmessage.MempoolEntry, 0) receiving := make([]*appmessage.MempoolEntry, 0)
scriptPublicKey, err := txscript.PayToAddrScript(address)
if err != nil {
errorMessage := &appmessage.GetMempoolEntriesByAddressesResponseMessage{}
errorMessage.Error = appmessage.RPCErrorf("Could not extract scriptPublicKey from address '%s': %s", addressString, err)
return errorMessage, nil
}
if !getMempoolEntriesByAddressesRequest.FilterTransactionPool { if !getMempoolEntriesByAddressesRequest.FilterTransactionPool {
if transaction, found := sendingInTransactionPool[address.String()]; found { if transaction, found := sendingInTransactionPool[scriptPublicKey.String()]; found {
rpcTransaction := appmessage.DomainTransactionToRPCTransaction(transaction) rpcTransaction := appmessage.DomainTransactionToRPCTransaction(transaction)
err := context.PopulateTransactionWithVerboseData(rpcTransaction, nil) err := context.PopulateTransactionWithVerboseData(rpcTransaction, nil)
if err != nil { if err != nil {
@ -49,7 +57,7 @@ func HandleGetMempoolEntriesByAddresses(context *rpccontext.Context, _ *router.R
) )
} }
if transaction, found := receivingInTransactionPool[address.String()]; found { if transaction, found := receivingInTransactionPool[scriptPublicKey.String()]; found {
rpcTransaction := appmessage.DomainTransactionToRPCTransaction(transaction) rpcTransaction := appmessage.DomainTransactionToRPCTransaction(transaction)
err := context.PopulateTransactionWithVerboseData(rpcTransaction, nil) err := context.PopulateTransactionWithVerboseData(rpcTransaction, nil)
if err != nil { if err != nil {
@ -66,7 +74,7 @@ func HandleGetMempoolEntriesByAddresses(context *rpccontext.Context, _ *router.R
} }
if getMempoolEntriesByAddressesRequest.IncludeOrphanPool { if getMempoolEntriesByAddressesRequest.IncludeOrphanPool {
if transaction, found := sendingInOrphanPool[address.String()]; found { if transaction, found := sendingInOrphanPool[scriptPublicKey.String()]; found {
rpcTransaction := appmessage.DomainTransactionToRPCTransaction(transaction) rpcTransaction := appmessage.DomainTransactionToRPCTransaction(transaction)
err := context.PopulateTransactionWithVerboseData(rpcTransaction, nil) err := context.PopulateTransactionWithVerboseData(rpcTransaction, nil)
if err != nil { if err != nil {
@ -81,7 +89,7 @@ func HandleGetMempoolEntriesByAddresses(context *rpccontext.Context, _ *router.R
) )
} }
if transaction, found := receivingInOrphanPool[address.String()]; found { if transaction, found := receivingInOrphanPool[scriptPublicKey.String()]; found {
rpcTransaction := appmessage.DomainTransactionToRPCTransaction(transaction) rpcTransaction := appmessage.DomainTransactionToRPCTransaction(transaction)
err := context.PopulateTransactionWithVerboseData(rpcTransaction, nil) err := context.PopulateTransactionWithVerboseData(rpcTransaction, nil)
if err != nil { if err != nil {

View File

@ -2,6 +2,7 @@ package externalapi
import ( import (
"bytes" "bytes"
"encoding/binary"
"fmt" "fmt"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -242,6 +243,23 @@ func (spk *ScriptPublicKey) Equal(other *ScriptPublicKey) bool {
return bytes.Equal(spk.Script, other.Script) return bytes.Equal(spk.Script, other.Script)
} }
// String stringifies a ScriptPublicKey.
func (spk *ScriptPublicKey) String() string {
var versionBytes = make([]byte, 2) // uint16
binary.LittleEndian.PutUint16(versionBytes, spk.Version)
versionString := string(versionBytes)
scriptString := string(spk.Script)
return versionString + scriptString
}
// NewScriptPublicKeyFromString converts the given string to a scriptPublicKey
func NewScriptPublicKeyFromString(ScriptPublicKeyString string) *ScriptPublicKey {
bytes := []byte(ScriptPublicKeyString)
version := binary.LittleEndian.Uint16(bytes[:2])
script := bytes[2:]
return &ScriptPublicKey{Script: script, Version: version}
}
// DomainTransactionOutput represents a Kaspad transaction output // DomainTransactionOutput represents a Kaspad transaction output
type DomainTransactionOutput struct { type DomainTransactionOutput struct {
Value uint64 Value uint64

View File

@ -15,3 +15,6 @@ type OutpointToUTXOEntryMap map[externalapi.DomainOutpoint]externalapi.UTXOEntry
// OutpointToTransactionMap maps an outpoint to a MempoolTransaction // OutpointToTransactionMap maps an outpoint to a MempoolTransaction
type OutpointToTransactionMap map[externalapi.DomainOutpoint]*MempoolTransaction type OutpointToTransactionMap map[externalapi.DomainOutpoint]*MempoolTransaction
// ScriptPublicKeyStringToDomainTransaction maps an outpoint to a DomainTransaction
type ScriptPublicKeyStringToDomainTransaction map[string]*externalapi.DomainTransaction

View File

@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants" "github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors" "github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
@ -345,11 +344,11 @@ func (op *orphansPool) getOrphanTransaction(transactionID *externalapi.DomainTra
} }
func (op *orphansPool) getOrphanTransactionsByAddresses(clone bool) ( func (op *orphansPool) getOrphanTransactionsByAddresses(clone bool) (
sending map[string]*externalapi.DomainTransaction, sending model.ScriptPublicKeyStringToDomainTransaction,
receiving map[string]*externalapi.DomainTransaction, receiving model.ScriptPublicKeyStringToDomainTransaction,
err error) { err error) {
sending = make(map[string]*externalapi.DomainTransaction) sending = make(model.ScriptPublicKeyStringToDomainTransaction)
receiving = make(map[string]*externalapi.DomainTransaction) receiving = make(model.ScriptPublicKeyStringToDomainTransaction)
var transaction *externalapi.DomainTransaction var transaction *externalapi.DomainTransaction
for _, mempoolTransaction := range op.allOrphans { for _, mempoolTransaction := range op.allOrphans {
if clone { if clone {
@ -361,24 +360,11 @@ func (op *orphansPool) getOrphanTransactionsByAddresses(clone bool) (
if input.UTXOEntry == nil { //this is not a bug, but a valid state of orphan transactions with missing outpoints. if input.UTXOEntry == nil { //this is not a bug, but a valid state of orphan transactions with missing outpoints.
continue continue
} }
_, address, err := txscript.ExtractScriptPubKeyAddress(input.UTXOEntry.ScriptPublicKey(), op.mempool.params)
if err != nil { sending[input.UTXOEntry.ScriptPublicKey().String()] = transaction
return nil, nil, err
}
if address == nil { //none standard tx
continue
}
sending[address.String()] = transaction
} }
for _, output := range transaction.Outputs { for _, output := range transaction.Outputs {
_, address, err := txscript.ExtractScriptPubKeyAddress(output.ScriptPublicKey, op.mempool.params) receiving[output.ScriptPublicKey.String()] = transaction
if err != nil {
return nil, nil, err
}
if address == nil { //none standard tx
continue
}
receiving[address.String()] = transaction
} }
} }

View File

@ -7,7 +7,6 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing" "github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
"github.com/kaspanet/kaspad/domain/miningmanager/mempool/model" "github.com/kaspanet/kaspad/domain/miningmanager/mempool/model"
) )
@ -221,11 +220,11 @@ func (tp *transactionsPool) getTransaction(transactionID *externalapi.DomainTran
} }
func (tp *transactionsPool) getTransactionsByAddresses(clone bool) ( func (tp *transactionsPool) getTransactionsByAddresses(clone bool) (
sending map[string]*externalapi.DomainTransaction, sending model.ScriptPublicKeyStringToDomainTransaction,
receiving map[string]*externalapi.DomainTransaction, receiving model.ScriptPublicKeyStringToDomainTransaction,
err error) { err error) {
sending = make(map[string]*externalapi.DomainTransaction) sending = make(model.ScriptPublicKeyStringToDomainTransaction)
receiving = make(map[string]*externalapi.DomainTransaction) receiving = make(model.ScriptPublicKeyStringToDomainTransaction)
var transaction *externalapi.DomainTransaction var transaction *externalapi.DomainTransaction
for _, mempoolTransaction := range tp.allTransactions { for _, mempoolTransaction := range tp.allTransactions {
if clone { if clone {
@ -237,27 +236,12 @@ func (tp *transactionsPool) getTransactionsByAddresses(clone bool) (
if input.UTXOEntry == nil { //this should be fixed if input.UTXOEntry == nil { //this should be fixed
return nil, nil, errors.Errorf("Mempool transaction %s is missing an UTXOEntry. This should be fixed, and not happen", consensushashing.TransactionID(transaction).String()) return nil, nil, errors.Errorf("Mempool transaction %s is missing an UTXOEntry. This should be fixed, and not happen", consensushashing.TransactionID(transaction).String())
} }
_, address, err := txscript.ExtractScriptPubKeyAddress(input.UTXOEntry.ScriptPublicKey(), tp.mempool.params) sending[input.UTXOEntry.ScriptPublicKey().String()] = transaction
if err != nil {
return nil, nil, err
}
if address == nil { //ignore none-standard script
continue
}
sending[address.String()] = transaction
} }
for _, output := range transaction.Outputs { for _, output := range transaction.Outputs {
_, address, err := txscript.ExtractScriptPubKeyAddress(output.ScriptPublicKey, tp.mempool.params) receiving[output.ScriptPublicKey.String()] = transaction
if err != nil {
return nil, nil, err
}
if address == nil { //ignore none-standard script
continue
}
receiving[address.String()] = transaction
} }
} }
return sending, receiving, nil return sending, receiving, nil
} }

View File

@ -1,7 +1,6 @@
package utxoindex package utxoindex
import ( import (
"encoding/binary"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
) )
@ -22,22 +21,3 @@ type UTXOChanges struct {
Added map[ScriptPublicKeyString]UTXOOutpointEntryPairs Added map[ScriptPublicKeyString]UTXOOutpointEntryPairs
Removed map[ScriptPublicKeyString]UTXOOutpointEntryPairs Removed map[ScriptPublicKeyString]UTXOOutpointEntryPairs
} }
// ConvertScriptPublicKeyToString converts the given scriptPublicKey to a string
func ConvertScriptPublicKeyToString(scriptPublicKey *externalapi.ScriptPublicKey) ScriptPublicKeyString {
var versionBytes = make([]byte, 2) // uint16
binary.LittleEndian.PutUint16(versionBytes, scriptPublicKey.Version)
versionString := ScriptPublicKeyString(versionBytes)
scriptString := ScriptPublicKeyString(scriptPublicKey.Script)
return versionString + scriptString
}
// ConvertStringToScriptPublicKey converts the given string to a scriptPublicKey
func ConvertStringToScriptPublicKey(string ScriptPublicKeyString) *externalapi.ScriptPublicKey {
bytes := []byte(string)
version := binary.LittleEndian.Uint16(bytes[:2])
script := bytes[2:]
return &externalapi.ScriptPublicKey{Script: script, Version: version}
}

View File

@ -32,7 +32,7 @@ func newUTXOIndexStore(database database.Database) *utxoIndexStore {
func (uis *utxoIndexStore) add(scriptPublicKey *externalapi.ScriptPublicKey, outpoint *externalapi.DomainOutpoint, utxoEntry externalapi.UTXOEntry) error { func (uis *utxoIndexStore) add(scriptPublicKey *externalapi.ScriptPublicKey, outpoint *externalapi.DomainOutpoint, utxoEntry externalapi.UTXOEntry) error {
key := ConvertScriptPublicKeyToString(scriptPublicKey) key := ScriptPublicKeyString(scriptPublicKey.String())
log.Tracef("Adding outpoint %s:%d to scriptPublicKey %s", log.Tracef("Adding outpoint %s:%d to scriptPublicKey %s",
outpoint.TransactionID, outpoint.Index, key) outpoint.TransactionID, outpoint.Index, key)
@ -66,7 +66,7 @@ func (uis *utxoIndexStore) add(scriptPublicKey *externalapi.ScriptPublicKey, out
} }
func (uis *utxoIndexStore) remove(scriptPublicKey *externalapi.ScriptPublicKey, outpoint *externalapi.DomainOutpoint, utxoEntry externalapi.UTXOEntry) error { func (uis *utxoIndexStore) remove(scriptPublicKey *externalapi.ScriptPublicKey, outpoint *externalapi.DomainOutpoint, utxoEntry externalapi.UTXOEntry) error {
key := ConvertScriptPublicKeyToString(scriptPublicKey) key := ScriptPublicKeyString(scriptPublicKey.String())
log.Tracef("Removing outpoint %s:%d from scriptPublicKey %s", log.Tracef("Removing outpoint %s:%d from scriptPublicKey %s",
outpoint.TransactionID, outpoint.Index, key) outpoint.TransactionID, outpoint.Index, key)
@ -122,7 +122,7 @@ func (uis *utxoIndexStore) commit() error {
toRemoveSompiSupply := uint64(0) toRemoveSompiSupply := uint64(0)
for scriptPublicKeyString, toRemoveUTXOOutpointEntryPairs := range uis.toRemove { for scriptPublicKeyString, toRemoveUTXOOutpointEntryPairs := range uis.toRemove {
scriptPublicKey := ConvertStringToScriptPublicKey(scriptPublicKeyString) scriptPublicKey := externalapi.NewScriptPublicKeyFromString(string(scriptPublicKeyString))
bucket := uis.bucketForScriptPublicKey(scriptPublicKey) bucket := uis.bucketForScriptPublicKey(scriptPublicKey)
for outpointToRemove, utxoEntryToRemove := range toRemoveUTXOOutpointEntryPairs { for outpointToRemove, utxoEntryToRemove := range toRemoveUTXOOutpointEntryPairs {
key, err := uis.convertOutpointToKey(bucket, &outpointToRemove) key, err := uis.convertOutpointToKey(bucket, &outpointToRemove)
@ -140,7 +140,7 @@ func (uis *utxoIndexStore) commit() error {
toAddSompiSupply := uint64(0) toAddSompiSupply := uint64(0)
for scriptPublicKeyString, toAddUTXOOutpointEntryPairs := range uis.toAdd { for scriptPublicKeyString, toAddUTXOOutpointEntryPairs := range uis.toAdd {
scriptPublicKey := ConvertStringToScriptPublicKey(scriptPublicKeyString) scriptPublicKey := externalapi.NewScriptPublicKeyFromString(string(scriptPublicKeyString))
bucket := uis.bucketForScriptPublicKey(scriptPublicKey) bucket := uis.bucketForScriptPublicKey(scriptPublicKey)
for outpointToAdd, utxoEntryToAdd := range toAddUTXOOutpointEntryPairs { for outpointToAdd, utxoEntryToAdd := range toAddUTXOOutpointEntryPairs {
key, err := uis.convertOutpointToKey(bucket, &outpointToAdd) key, err := uis.convertOutpointToKey(bucket, &outpointToAdd)