From 1f4e78d25d2a929597f1699560a4210470b65a08 Mon Sep 17 00:00:00 2001 From: axenteoctavian Date: Thu, 21 Nov 2024 12:15:15 +0200 Subject: [PATCH 1/3] Tx notarization checker --- cmd/proxy/main.go | 1 + factory/interface.go | 5 ++++ factory/runType/runTypeComponents.go | 8 +++++- factory/runType/runTypeComponentsFactory.go | 8 +++++- factory/runType/runTypeComponentsHandler.go | 16 +++++++++++ .../runType/runTypeComponentsHandler_test.go | 5 ++++ .../sovereignRunTypeComponentsFactory.go | 8 +++++- process/errors.go | 3 +++ .../factory/sovereignTxNotarizationChecker.go | 22 +++++++++++++++ .../sovereignTxNotarizationChecker_test.go | 23 ++++++++++++++++ .../factory/transactionProcessorFactory.go | 4 +++ process/factory/txNotarizationChecker.go | 22 +++++++++++++++ process/factory/txNotarizationChecker_test.go | 27 +++++++++++++++++++ process/interface.go | 6 +++++ process/transactionProcessor.go | 13 ++++++--- 15 files changed, 165 insertions(+), 6 deletions(-) create mode 100644 process/factory/sovereignTxNotarizationChecker.go create mode 100644 process/factory/sovereignTxNotarizationChecker_test.go create mode 100644 process/factory/txNotarizationChecker.go create mode 100644 process/factory/txNotarizationChecker_test.go diff --git a/cmd/proxy/main.go b/cmd/proxy/main.go index aa93e4ad..3c013af9 100644 --- a/cmd/proxy/main.go +++ b/cmd/proxy/main.go @@ -487,6 +487,7 @@ func createVersionsRegistry( hasher, marshalizer, cfg.GeneralSettings.AllowEntireTxPoolFetch, + runTypeComponents, ) if err != nil { return nil, err diff --git a/factory/interface.go b/factory/interface.go index ae3435e6..e4a22950 100644 --- a/factory/interface.go +++ b/factory/interface.go @@ -1,5 +1,9 @@ package factory +import ( + "github.com/multiversx/mx-chain-proxy-go/process" +) + // ComponentHandler defines the actions common to all component handlers type ComponentHandler interface { Create() error @@ -16,6 +20,7 @@ type RunTypeComponentsHandler interface { // RunTypeComponentsHolder holds the run type components type RunTypeComponentsHolder interface { + TxNotarizationCheckerHandlerCreator() process.TxNotarizationCheckerHandler Create() error Close() error CheckSubcomponents() error diff --git a/factory/runType/runTypeComponents.go b/factory/runType/runTypeComponents.go index c960293b..db4a7a5f 100644 --- a/factory/runType/runTypeComponents.go +++ b/factory/runType/runTypeComponents.go @@ -1,6 +1,12 @@ package runType -type runTypeComponents struct{} +import ( + "github.com/multiversx/mx-chain-proxy-go/process" +) + +type runTypeComponents struct { + txNotarizationCheckerHandlerCreator process.TxNotarizationCheckerHandler +} // Close does nothing func (rtc *runTypeComponents) Close() error { diff --git a/factory/runType/runTypeComponentsFactory.go b/factory/runType/runTypeComponentsFactory.go index 24ad9f56..30ec5f53 100644 --- a/factory/runType/runTypeComponentsFactory.go +++ b/factory/runType/runTypeComponentsFactory.go @@ -1,5 +1,9 @@ package runType +import ( + "github.com/multiversx/mx-chain-proxy-go/process/factory" +) + type runTypeComponentsFactory struct{} // NewRunTypeComponentsFactory will return a new instance of run type components factory @@ -9,7 +13,9 @@ func NewRunTypeComponentsFactory() *runTypeComponentsFactory { // Create will create the run type components func (rtcf *runTypeComponentsFactory) Create() *runTypeComponents { - return &runTypeComponents{} + return &runTypeComponents{ + txNotarizationCheckerHandlerCreator: factory.NewTxNotarizationChecker(), + } } // IsInterfaceNil returns true if there is no value under the interface diff --git a/factory/runType/runTypeComponentsHandler.go b/factory/runType/runTypeComponentsHandler.go index 8f74e1a6..4548cab0 100644 --- a/factory/runType/runTypeComponentsHandler.go +++ b/factory/runType/runTypeComponentsHandler.go @@ -6,6 +6,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-proxy-go/factory" + "github.com/multiversx/mx-chain-proxy-go/process" ) const runTypeComponentsName = "managedRunTypeComponents" @@ -69,9 +70,24 @@ func (mrtc *managedRunTypeComponents) CheckSubcomponents() error { if check.IfNil(mrtc.runTypeComponents) { return factory.ErrNilRunTypeComponents } + if check.IfNil(mrtc.txNotarizationCheckerHandlerCreator) { + return process.ErrNilTxNotarizationCheckerHandler + } return nil } +// TxNotarizationCheckerHandlerCreator returns tx notarization checker handler +func (mrtc *managedRunTypeComponents) TxNotarizationCheckerHandlerCreator() process.TxNotarizationCheckerHandler { + mrtc.mutRunTypeCoreComponents.RLock() + defer mrtc.mutRunTypeCoreComponents.RUnlock() + + if check.IfNil(mrtc.runTypeComponents) { + return nil + } + + return mrtc.runTypeComponents.txNotarizationCheckerHandlerCreator +} + // IsInterfaceNil returns true if the interface is nil func (mrtc *managedRunTypeComponents) IsInterfaceNil() bool { return mrtc == nil diff --git a/factory/runType/runTypeComponentsHandler_test.go b/factory/runType/runTypeComponentsHandler_test.go index b3f1bcfa..9cd5d46a 100644 --- a/factory/runType/runTypeComponentsHandler_test.go +++ b/factory/runType/runTypeComponentsHandler_test.go @@ -38,9 +38,13 @@ func TestManagedRunTypeComponents_Create(t *testing.T) { managedRunTypeComponents, err := createComponents() require.NoError(t, err) + require.Nil(t, managedRunTypeComponents.TxNotarizationCheckerHandlerCreator()) + err = managedRunTypeComponents.Create() require.NoError(t, err) + require.NotNil(t, managedRunTypeComponents.TxNotarizationCheckerHandlerCreator()) + require.Equal(t, runTypeComponentsName, managedRunTypeComponents.String()) require.NoError(t, managedRunTypeComponents.Close()) }) @@ -56,6 +60,7 @@ func TestManagedRunTypeComponents_Close(t *testing.T) { require.NoError(t, err) require.NoError(t, managedRunTypeComponents.Close()) + require.Nil(t, managedRunTypeComponents.TxNotarizationCheckerHandlerCreator()) } func TestManagedRunTypeComponents_CheckSubcomponents(t *testing.T) { diff --git a/factory/runType/sovereignRunTypeComponentsFactory.go b/factory/runType/sovereignRunTypeComponentsFactory.go index fd5226a5..33717b36 100644 --- a/factory/runType/sovereignRunTypeComponentsFactory.go +++ b/factory/runType/sovereignRunTypeComponentsFactory.go @@ -1,5 +1,9 @@ package runType +import ( + "github.com/multiversx/mx-chain-proxy-go/process/factory" +) + type sovereignRunTypeComponentsFactory struct{} // NewSovereignRunTypeComponentsFactory will return a new instance of sovereign run type components factory @@ -9,7 +13,9 @@ func NewSovereignRunTypeComponentsFactory() *sovereignRunTypeComponentsFactory { // Create will create the run type components func (srtcf *sovereignRunTypeComponentsFactory) Create() *runTypeComponents { - return &runTypeComponents{} + return &runTypeComponents{ + txNotarizationCheckerHandlerCreator: factory.NewSovereignTxNotarizationChecker(), + } } // IsInterfaceNil returns true if there is no value under the interface diff --git a/process/errors.go b/process/errors.go index 8060b7b4..3f8279a6 100644 --- a/process/errors.go +++ b/process/errors.go @@ -112,3 +112,6 @@ var ErrEmptyPubKey = errors.New("public key is empty") // ErrNilHttpClient signals that a nil http client has been provided var ErrNilHttpClient = errors.New("nil http client") + +// ErrNilTxNotarizationCheckerHandler signals that nil tx notarization checker handler has been provided +var ErrNilTxNotarizationCheckerHandler = errors.New("nil tx notarization checker handler has been provided") diff --git a/process/factory/sovereignTxNotarizationChecker.go b/process/factory/sovereignTxNotarizationChecker.go new file mode 100644 index 00000000..c61c78da --- /dev/null +++ b/process/factory/sovereignTxNotarizationChecker.go @@ -0,0 +1,22 @@ +package factory + +import ( + "github.com/multiversx/mx-chain-core-go/data/transaction" +) + +type sovereignTxNotarizationChecker struct{} + +// NewSovereignTxNotarizationChecker creates a new sovereign tx notarization checker +func NewSovereignTxNotarizationChecker() *sovereignTxNotarizationChecker { + return &sovereignTxNotarizationChecker{} +} + +// IsNotarized returns if tx is notarized +func (stnc *sovereignTxNotarizationChecker) IsNotarized(_ transaction.ApiTransactionResult) bool { + return true +} + +// IsInterfaceNil returns true if there is no value under the interface +func (stnc *sovereignTxNotarizationChecker) IsInterfaceNil() bool { + return stnc == nil +} diff --git a/process/factory/sovereignTxNotarizationChecker_test.go b/process/factory/sovereignTxNotarizationChecker_test.go new file mode 100644 index 00000000..25e18504 --- /dev/null +++ b/process/factory/sovereignTxNotarizationChecker_test.go @@ -0,0 +1,23 @@ +package factory + +import ( + "testing" + + "github.com/multiversx/mx-chain-core-go/data/transaction" + "github.com/stretchr/testify/require" +) + +func TestSovereignTxNotarizationChecker(t *testing.T) { + t.Parallel() + + tnc := NewTxNotarizationChecker() + require.False(t, tnc.IsInterfaceNil()) +} + +func TestSovereignTxNotarizationChecker_IsNotarized(t *testing.T) { + t.Parallel() + + tnc := NewTxNotarizationChecker() + isNotarized := tnc.IsNotarized(transaction.ApiTransactionResult{}) + require.True(t, isNotarized) +} diff --git a/process/factory/transactionProcessorFactory.go b/process/factory/transactionProcessorFactory.go index 1055c1fd..0e46503f 100644 --- a/process/factory/transactionProcessorFactory.go +++ b/process/factory/transactionProcessorFactory.go @@ -4,7 +4,9 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-proxy-go/facade" + "github.com/multiversx/mx-chain-proxy-go/factory" "github.com/multiversx/mx-chain-proxy-go/process" "github.com/multiversx/mx-chain-proxy-go/process/logsevents" "github.com/multiversx/mx-chain-proxy-go/process/txcost" @@ -17,6 +19,7 @@ func CreateTransactionProcessor( hasher hashing.Hasher, marshalizer marshal.Marshalizer, allowEntireTxPoolFetch bool, + runTypeComponents factory.RunTypeComponentsHolder, ) (facade.TransactionProcessor, error) { newTxCostProcessor := func() (process.TransactionCostHandler, error) { return txcost.NewTransactionCostProcessor( @@ -38,5 +41,6 @@ func CreateTransactionProcessor( newTxCostProcessor, logsMerger, allowEntireTxPoolFetch, + runTypeComponents.TxNotarizationCheckerHandlerCreator(), ) } diff --git a/process/factory/txNotarizationChecker.go b/process/factory/txNotarizationChecker.go new file mode 100644 index 00000000..5db993f1 --- /dev/null +++ b/process/factory/txNotarizationChecker.go @@ -0,0 +1,22 @@ +package factory + +import ( + "github.com/multiversx/mx-chain-core-go/data/transaction" +) + +type txNotarizationChecker struct{} + +// NewTxNotarizationChecker creates a new tx notarization checker +func NewTxNotarizationChecker() *txNotarizationChecker { + return &txNotarizationChecker{} +} + +// IsNotarized returns if tx is notarized +func (tnc *txNotarizationChecker) IsNotarized(tx transaction.ApiTransactionResult) bool { + return tx.NotarizedAtSourceInMetaNonce > 0 && tx.NotarizedAtDestinationInMetaNonce > 0 +} + +// IsInterfaceNil returns true if there is no value under the interface +func (tnc *txNotarizationChecker) IsInterfaceNil() bool { + return tnc == nil +} diff --git a/process/factory/txNotarizationChecker_test.go b/process/factory/txNotarizationChecker_test.go new file mode 100644 index 00000000..7e26136f --- /dev/null +++ b/process/factory/txNotarizationChecker_test.go @@ -0,0 +1,27 @@ +package factory + +import ( + "testing" + + "github.com/multiversx/mx-chain-core-go/data/transaction" + "github.com/stretchr/testify/require" +) + +func TestTxNotarizationChecker(t *testing.T) { + t.Parallel() + + tnc := NewTxNotarizationChecker() + require.False(t, tnc.IsInterfaceNil()) +} + +func TestTxNotarizationChecker_IsNotarized(t *testing.T) { + t.Parallel() + + tnc := NewTxNotarizationChecker() + tx := transaction.ApiTransactionResult{ + NotarizedAtSourceInMetaNonce: 1, + NotarizedAtDestinationInMetaNonce: 1, + } + isNotarized := tnc.IsNotarized(tx) + require.True(t, isNotarized) +} diff --git a/process/interface.go b/process/interface.go index f424bdfc..602e62bd 100644 --- a/process/interface.go +++ b/process/interface.go @@ -85,3 +85,9 @@ type StatusMetricsProvider interface { type HttpClient interface { Do(req *http.Request) (*http.Response, error) } + +// TxNotarizationCheckerHandler defines a TxNotarizationCheckerHandler behavior +type TxNotarizationCheckerHandler interface { + IsNotarized(tx transaction.ApiTransactionResult) bool + IsInterfaceNil() bool +} diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index b91cf6c2..be586473 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -11,6 +11,7 @@ import ( "github.com/multiversx/mx-chain-core-go/data/transaction" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-proxy-go/api/errors" "github.com/multiversx/mx-chain-proxy-go/data" ) @@ -83,6 +84,7 @@ type TransactionProcessor struct { newTxCostProcessor func() (TransactionCostHandler, error) mergeLogsHandler LogsMergerHandler shouldAllowEntireTxPoolFetch bool + txNotarizationChecker TxNotarizationCheckerHandler } // NewTransactionProcessor creates a new instance of TransactionProcessor @@ -94,6 +96,7 @@ func NewTransactionProcessor( newTxCostProcessor func() (TransactionCostHandler, error), logsMerger LogsMergerHandler, allowEntireTxPoolFetch bool, + txNotarizationChecker TxNotarizationCheckerHandler, ) (*TransactionProcessor, error) { if check.IfNil(proc) { return nil, ErrNilCoreProcessor @@ -113,6 +116,9 @@ func NewTransactionProcessor( if check.IfNil(logsMerger) { return nil, ErrNilLogsMerger } + if check.IfNil(txNotarizationChecker) { + return nil, ErrNilTxNotarizationCheckerHandler + } // no reason to get this from configs. If we are going to change the marshaller for the relayed transaction v1, // we will need also an enable epoch handler @@ -126,6 +132,7 @@ func NewTransactionProcessor( mergeLogsHandler: logsMerger, shouldAllowEntireTxPoolFetch: allowEntireTxPoolFetch, relayedTxsMarshaller: relayedTxsMarshaller, + txNotarizationChecker: txNotarizationChecker, }, nil } @@ -453,7 +460,7 @@ func (tp *TransactionProcessor) computeTransactionStatus(tx *transaction.ApiTran } } - if checkIfMoveBalanceNotarized(tx) { + if tp.checkIfMoveBalanceNotarized(tx) { return &data.ProcessStatusResponse{ Status: string(tx.Status), } @@ -580,8 +587,8 @@ func checkIfCompleted(logs []*transaction.ApiLogs) bool { return found } -func checkIfMoveBalanceNotarized(tx *transaction.ApiTransactionResult) bool { - isNotarized := tx.NotarizedAtSourceInMetaNonce > 0 && tx.NotarizedAtDestinationInMetaNonce > 0 +func (tp *TransactionProcessor) checkIfMoveBalanceNotarized(tx *transaction.ApiTransactionResult) bool { + isNotarized := tp.txNotarizationChecker.IsNotarized(*tx) if !isNotarized { return false } From fa31f97c896791c92c21e7603751d67fa43ee618 Mon Sep 17 00:00:00 2001 From: axenteoctavian Date: Fri, 22 Nov 2024 10:12:50 +0200 Subject: [PATCH 2/3] fixes after review --- .../factory/sovereignTxNotarizationChecker.go | 2 +- process/factory/txNotarizationChecker_test.go | 21 ++++++++++++------- process/interface.go | 3 ++- process/transactionProcessor.go | 3 +-- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/process/factory/sovereignTxNotarizationChecker.go b/process/factory/sovereignTxNotarizationChecker.go index c61c78da..9712861e 100644 --- a/process/factory/sovereignTxNotarizationChecker.go +++ b/process/factory/sovereignTxNotarizationChecker.go @@ -11,7 +11,7 @@ func NewSovereignTxNotarizationChecker() *sovereignTxNotarizationChecker { return &sovereignTxNotarizationChecker{} } -// IsNotarized returns if tx is notarized +// IsNotarized returns true func (stnc *sovereignTxNotarizationChecker) IsNotarized(_ transaction.ApiTransactionResult) bool { return true } diff --git a/process/factory/txNotarizationChecker_test.go b/process/factory/txNotarizationChecker_test.go index 7e26136f..928e03fa 100644 --- a/process/factory/txNotarizationChecker_test.go +++ b/process/factory/txNotarizationChecker_test.go @@ -17,11 +17,18 @@ func TestTxNotarizationChecker(t *testing.T) { func TestTxNotarizationChecker_IsNotarized(t *testing.T) { t.Parallel() - tnc := NewTxNotarizationChecker() - tx := transaction.ApiTransactionResult{ - NotarizedAtSourceInMetaNonce: 1, - NotarizedAtDestinationInMetaNonce: 1, - } - isNotarized := tnc.IsNotarized(tx) - require.True(t, isNotarized) + t.Run("tx is notarized, should work", func(t *testing.T) { + tnc := NewTxNotarizationChecker() + tx := transaction.ApiTransactionResult{ + NotarizedAtSourceInMetaNonce: 1, + NotarizedAtDestinationInMetaNonce: 1, + } + isNotarized := tnc.IsNotarized(tx) + require.True(t, isNotarized) + }) + t.Run("tx is not notarized, should work", func(t *testing.T) { + tnc := NewTxNotarizationChecker() + isNotarized := tnc.IsNotarized(transaction.ApiTransactionResult{}) + require.False(t, isNotarized) + }) } diff --git a/process/interface.go b/process/interface.go index 602e62bd..7e5681f2 100644 --- a/process/interface.go +++ b/process/interface.go @@ -7,6 +7,7 @@ import ( "github.com/multiversx/mx-chain-core-go/data/transaction" "github.com/multiversx/mx-chain-core-go/data/vm" crypto "github.com/multiversx/mx-chain-crypto-go" + "github.com/multiversx/mx-chain-proxy-go/common" "github.com/multiversx/mx-chain-proxy-go/data" "github.com/multiversx/mx-chain-proxy-go/observer" @@ -86,7 +87,7 @@ type HttpClient interface { Do(req *http.Request) (*http.Response, error) } -// TxNotarizationCheckerHandler defines a TxNotarizationCheckerHandler behavior +// TxNotarizationCheckerHandler defines what tx notarization checked should do type TxNotarizationCheckerHandler interface { IsNotarized(tx transaction.ApiTransactionResult) bool IsInterfaceNil() bool diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index be586473..4c854b7d 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -588,8 +588,7 @@ func checkIfCompleted(logs []*transaction.ApiLogs) bool { } func (tp *TransactionProcessor) checkIfMoveBalanceNotarized(tx *transaction.ApiTransactionResult) bool { - isNotarized := tp.txNotarizationChecker.IsNotarized(*tx) - if !isNotarized { + if !tp.txNotarizationChecker.IsNotarized(*tx) { return false } isMoveBalance := tx.ProcessingTypeOnSource == moveBalanceDescriptor && tx.ProcessingTypeOnDestination == moveBalanceDescriptor From 3883b5c780f328b0b6b72362da66c9b710a007e1 Mon Sep 17 00:00:00 2001 From: axenteoctavian Date: Fri, 22 Nov 2024 15:58:53 +0200 Subject: [PATCH 3/3] fixes after review --- process/factory/txNotarizationChecker_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/process/factory/txNotarizationChecker_test.go b/process/factory/txNotarizationChecker_test.go index 928e03fa..be530ca0 100644 --- a/process/factory/txNotarizationChecker_test.go +++ b/process/factory/txNotarizationChecker_test.go @@ -17,7 +17,7 @@ func TestTxNotarizationChecker(t *testing.T) { func TestTxNotarizationChecker_IsNotarized(t *testing.T) { t.Parallel() - t.Run("tx is notarized, should work", func(t *testing.T) { + t.Run("tx is notarized", func(t *testing.T) { tnc := NewTxNotarizationChecker() tx := transaction.ApiTransactionResult{ NotarizedAtSourceInMetaNonce: 1, @@ -26,7 +26,7 @@ func TestTxNotarizationChecker_IsNotarized(t *testing.T) { isNotarized := tnc.IsNotarized(tx) require.True(t, isNotarized) }) - t.Run("tx is not notarized, should work", func(t *testing.T) { + t.Run("tx is not notarized", func(t *testing.T) { tnc := NewTxNotarizationChecker() isNotarized := tnc.IsNotarized(transaction.ApiTransactionResult{}) require.False(t, isNotarized)