Skip to content

Commit

Permalink
rpcsrv: add getRawNotaryPool and getRawNotaryRequest
Browse files Browse the repository at this point in the history
getRawNotaryRequest takes a transaction hash and attempts to find the
corresponding transaction in the notary requests mempool. It searches
through all the verified main and fallback transactions.
getRawNotaryPool returns hashes from all the verified transactions
both main and fallback.

Signed-off-by: Tatiana Nesterenko <[email protected]>
  • Loading branch information
tatiana-nspcc committed Aug 22, 2023
1 parent e228233 commit 3918670
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 0 deletions.
46 changes: 46 additions & 0 deletions pkg/services/rpcsrv/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,9 @@ var rpcHandlers = map[string]func(*Server, params.Params) (any, *neorpc.Error){
"getpeers": (*Server).getPeers,
"getproof": (*Server).getProof,
"getrawmempool": (*Server).getRawMempool,
"getrawnotarypool": (*Server).getRawNotaryPool,
"getrawtransaction": (*Server).getrawtransaction,
"getrawnotaryrequest": (*Server).getRawNotaryRequest,
"getstate": (*Server).getState,
"getstateheight": (*Server).getStateHeight,
"getstateroot": (*Server).getStateRoot,
Expand Down Expand Up @@ -2936,3 +2938,47 @@ func (s *Server) Addresses() []string {
}
return res
}

func (s *Server) getRawNotaryPool(reqParams params.Params) (any, *neorpc.Error) {
if !s.chain.P2PSigExtensionsEnabled() {
return nil, neorpc.NewInternalServerError("P2PSignatureExtensions are disabled")
}
verbose, _ := reqParams.Value(0).GetBoolean()

nrp := s.coreServer.GetNotaryPool()
pool := nrp.GetVerifiedPoolTx()
if !verbose {
return pool, nil
}

Check warning on line 2952 in pkg/services/rpcsrv/server.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/rpcsrv/server.go#L2951-L2952

Added lines #L2951 - L2952 were not covered by tests
res := result.RawNotaryPool{}
for txMain, list := range pool {
hashes := result.NotaryHashes{MainTxHash: txMain}
hashes.FallbackTxHashes = append(hashes.FallbackTxHashes, list...)
res.NotaryHashes = append(res.NotaryHashes, hashes)
}
return res, nil
}

func (s *Server) getRawNotaryRequest(reqParams params.Params) (any, *neorpc.Error) {
if !s.chain.P2PSigExtensionsEnabled() {
return nil, neorpc.NewInternalServerError("P2PSignatureExtensions are disabled")
}

txHash, err := reqParams.Value(0).GetUint256()
if err != nil {
return nil, neorpc.ErrInvalidParams
}
nrp := s.coreServer.GetNotaryPool()
tx, ok := nrp.TryFindTransaction(txHash)
if !ok {
return nil, neorpc.ErrUnknownTransaction
}

Check warning on line 2975 in pkg/services/rpcsrv/server.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/rpcsrv/server.go#L2974-L2975

Added lines #L2974 - L2975 were not covered by tests

if v, _ := reqParams.Value(1).GetBoolean(); v {
res := result.TransactionOutputRaw{
Transaction: *tx,
}
return res, nil
}
return tx.Bytes(), nil

Check warning on line 2983 in pkg/services/rpcsrv/server.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/rpcsrv/server.go#L2983

Added line #L2983 was not covered by tests
}
101 changes: 101 additions & 0 deletions pkg/services/rpcsrv/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2003,6 +2003,107 @@ func TestSubmitNotaryRequest(t *testing.T) {
})
}

func TestGetRawNotaryPoolAndGetRawNotaryRequest(t *testing.T) {
var notaryRequest *payload.P2PNotaryRequest
rpcPool := `{"jsonrpc": "2.0", "id": 1, "method": "getrawnotarypool", "params": %s}`
rpcRequest := `{"jsonrpc": "2.0", "id": 1, "method": "getrawnotaryrequest", "params": ["%s", %d]}`

t.Run("disabled P2PSigExtensions", func(t *testing.T) {
chain, rpcSrv, httpSrv := initClearServerWithCustomConfig(t, func(c *config.Config) {
c.ProtocolConfiguration.P2PSigExtensions = false
})
defer chain.Close()
defer rpcSrv.Shutdown()
t.Run("getrawnotarypool", func(t *testing.T) {
body := doRPCCallOverHTTP(fmt.Sprintf(rpcPool, "[]"), httpSrv.URL, t)
checkErrGetResult(t, body, true, neorpc.InternalServerErrorCode)
})
t.Run("getrawnotaryrequest", func(t *testing.T) {
body := doRPCCallOverHTTP(fmt.Sprintf(rpcRequest, " ", 1), httpSrv.URL, t)
checkErrGetResult(t, body, true, neorpc.InternalServerErrorCode)
})
})

chain, rpcSrv, httpSrv := initServerWithInMemoryChainAndServices(t, false, true, false)
defer chain.Close()
defer rpcSrv.Shutdown()

submitNotaryRequest := func(t *testing.T, fail bool, errCode int64, params ...string) func(t *testing.T) {
return func(t *testing.T) {
rpcSubmit := `{"jsonrpc": "2.0", "id": 1, "method": "submitnotaryrequest", "params": %s}`
ps := `[` + strings.Join(params, ",") + `]`
req := fmt.Sprintf(rpcSubmit, ps)
body := doRPCCallOverHTTP(req, httpSrv.URL, t)
checkErrGetResult(t, body, fail, errCode)
}
}

compareTx := func(t *testing.T, expectedTx, actualTx transaction.Transaction) func(t *testing.T) {
return func(t *testing.T) {
require.Equal(t, expectedTx.Hash(), actualTx.Hash())
require.Equal(t, expectedTx.Nonce, actualTx.Nonce)
require.Equal(t, expectedTx.Sender(), actualTx.Sender())
require.Equal(t, expectedTx.Signers, actualTx.Signers)
require.Equal(t, expectedTx.ValidUntilBlock, actualTx.ValidUntilBlock)
require.Equal(t, expectedTx.Script, actualTx.Script)
require.Equal(t, expectedTx.Attributes, actualTx.Attributes)
}
}

t.Run("test getrawnotarypool", func(t *testing.T) {
t.Run("empty pool", func(t *testing.T) {
body := doRPCCallOverHTTP(fmt.Sprintf(rpcPool, "[true]"), httpSrv.URL, t)
res := checkErrGetResult(t, body, false, 0)
actual := new(result.RawNotaryPool)
require.NoError(t, json.Unmarshal(res, actual))
require.Equal(t, 0, len(actual.NotaryHashes))
})

t.Run("submit first valid notary request", func(t *testing.T) {
sender := testchain.PrivateKeyByID(0) // owner of the deposit in testchain
notaryRequest = createValidNotaryRequest(chain, sender, 1)
nrBytes, err := notaryRequest.Bytes()
require.NoError(t, err)
str := fmt.Sprintf(`"%s"`, base64.StdEncoding.EncodeToString(nrBytes))
submitNotaryRequest(t, false, 0, str)(t)
})

t.Run("get notary pool & check tx hashes", func(t *testing.T) {
body := doRPCCallOverHTTP(fmt.Sprintf(rpcPool, "[true]"), httpSrv.URL, t)
res := checkErrGetResult(t, body, false, 0)
actual := new(result.RawNotaryPool)
require.NoError(t, json.Unmarshal(res, actual))
require.Equal(t, 1, len(actual.NotaryHashes))
require.Equal(t, notaryRequest.MainTransaction.Hash(), actual.NotaryHashes[0].MainTxHash)
require.Equal(t, notaryRequest.FallbackTransaction.Hash(), actual.NotaryHashes[0].FallbackTxHashes[0])
})
})

t.Run("test getrawnotaryrequest", func(t *testing.T) {
t.Run("invalid param", func(t *testing.T) {
req := fmt.Sprintf(rpcRequest, "invalid", 1)
body := doRPCCallOverHTTP(req, httpSrv.URL, t)
checkErrGetResult(t, body, true, neorpc.InvalidParamsCode)
})
t.Run("mainTx", func(t *testing.T) {
req := fmt.Sprintf(rpcRequest, notaryRequest.MainTransaction.Hash().StringLE(), 1)
body := doRPCCallOverHTTP(req, httpSrv.URL, t)
res := checkErrGetResult(t, body, false, 0)
actual := new(result.TransactionOutputRaw)
require.NoError(t, json.Unmarshal(res, actual))
compareTx(t, *notaryRequest.MainTransaction, actual.Transaction)
})
t.Run("fallbackTx", func(t *testing.T) {
req := fmt.Sprintf(rpcRequest, notaryRequest.FallbackTransaction.Hash().StringLE(), 1)
body := doRPCCallOverHTTP(req, httpSrv.URL, t)
res := checkErrGetResult(t, body, false, 0)
actual := new(result.TransactionOutputRaw)
require.NoError(t, json.Unmarshal(res, actual))
compareTx(t, *notaryRequest.FallbackTransaction, actual.Transaction)
})
})
}

// createValidNotaryRequest creates and signs P2PNotaryRequest payload which can
// pass verification.
func createValidNotaryRequest(chain *core.Blockchain, sender *keys.PrivateKey, nonce uint32) *payload.P2PNotaryRequest {
Expand Down

0 comments on commit 3918670

Please sign in to comment.