Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get block notifications API #3781

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

lock9
Copy link

@lock9 lock9 commented Jan 6, 2025

Closes #3779.

It works but I don't know if this is the best way to do it.

Copy link
Member

@roman-khimov roman-khimov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one overall.

return nil, respErr
}

block, err := s.chain.GetBlock(hash)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need some GetTrimmedBlock or alike, this one does extract all transactions and we don't need them (only hash is needed for GetAppExecResults()). But it's an optimization in its essence, current code will work fine.

for _, tx := range block.Transactions {
aers, err := s.chain.GetAppExecResults(tx.Hash(), trigger.Application)
if err != nil {
continue
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return internal error? This means some DB inconsistency and the result can be incorrect.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vote up for error return.

}
}

// Also check for notifications from the block itself (PostPersist)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to keep the sequence correct and check for trigger.OnPersist before digging into transaction list.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may additionally extend neorpc.NotificaitonFilter with trigger parameter, it may be useful in some cases, what do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the use cases? People interested in block-level things (and not a lot happens there) probably pull block applogs directly and otherwise it's all Application.

pkg/services/rpcsrv/server.go Outdated Show resolved Hide resolved
pkg/services/rpcsrv/server.go Outdated Show resolved Hide resolved
}

// testComparator is a helper type for notification filtering
type testComparator struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can move these out into a separate file (along with the logic for appending to notifications.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I'd say that testComparator/testContainer is suitable for testing code, but not for the production code. Let's rename it to something more appropriate.

params: `["` + genesisBlockHash + `", {"contract":"` + testContractHashLE + `", "name":"Transfer"}]`,
result: func(e *executor) any { return []state.ContainedNotificationEvent{} },
check: func(t *testing.T, e *executor, acc any) {
res, ok := acc.([]state.ContainedNotificationEvent)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check for expected contents as well.

@roman-khimov
Copy link
Member

RPC client needs to be updated to support this as well.

Copy link
Member

@AnnaShaleva AnnaShaleva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A useful extension.

for _, tx := range block.Transactions {
aers, err := s.chain.GetAppExecResults(tx.Hash(), trigger.Application)
if err != nil {
continue
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vote up for error return.

}
}

// Also check for notifications from the block itself (PostPersist)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may additionally extend neorpc.NotificaitonFilter with trigger parameter, it may be useful in some cases, what do you think?

}

// testComparator is a helper type for notification filtering
type testComparator struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I'd say that testComparator/testContainer is suitable for testing code, but not for the production code. Let's rename it to something more appropriate.

pkg/services/rpcsrv/server_test.go Outdated Show resolved Hide resolved
pkg/services/rpcsrv/server.go Show resolved Hide resolved
pkg/services/rpcsrv/server.go Show resolved Hide resolved
@AnnaShaleva
Copy link
Member

Please, ensure testing jobs are passing. Currently, unit-tests, project linter and DCO checks are failing.

@lock9
Copy link
Author

lock9 commented Jan 15, 2025

Hey guys, got some busy days ahead. I'll come back to this in one or two weeks max. Sorry for the delay

@lock9 lock9 force-pushed the block-notifications branch from c1849a5 to dee62f4 Compare January 20, 2025 06:32
@lock9 lock9 force-pushed the block-notifications branch from dee62f4 to cb76197 Compare January 20, 2025 06:34
@lock9
Copy link
Author

lock9 commented Jan 20, 2025

PR Updated.

Changes:

  • Added GetTrimmedBlock and TrimmedBlock
    • Note: There's already the concept of 'trimmed block' and this name may not be ideal
  • Added a new struct "BlockNotifications", grouping notifications by trigger type
  • Updated the tests to use the neo token hash
  • Updated the tests to check the notification content
  • Changed the name of some functions/types
  • Moved reusable logic to the utils file
  • Added the new endpoint to the rpc docs file
  • Updated the client class to support the new endpoint

Still pending:

  • RPC Client tests

About trigger filters: I don't know/don't have an opinion.

return nil
}

func (b *TrimmedBlock) ToStackItem() stackitem.Item {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this necessary?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, remove it. We're only interested in proper deserialization from bytes.

Copy link

codecov bot commented Jan 20, 2025

Codecov Report

Attention: Patch coverage is 61.25000% with 62 lines in your changes missing coverage. Please review.

Project coverage is 82.99%. Comparing base (16a6a59) to head (d012a6b).

Files with missing lines Patch % Lines
pkg/core/block/block.go 45.33% 33 Missing and 8 partials ⚠️
pkg/services/rpcsrv/server.go 67.56% 9 Missing and 3 partials ⚠️
pkg/rpcclient/rpc.go 0.00% 6 Missing ⚠️
pkg/core/dao/dao.go 72.72% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3781      +/-   ##
==========================================
- Coverage   83.14%   82.99%   -0.16%     
==========================================
  Files         335      335              
  Lines       46896    47056     +160     
==========================================
+ Hits        38994    39054      +60     
- Misses       6310     6399      +89     
- Partials     1592     1603      +11     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@@ -248,6 +248,10 @@ block. It can be removed in future versions, but at the moment you can use it
to see how much GAS is burned with a particular block (because system fees are
burned).

#### `getblocknotifications` call

This method returns notifications from a block organized by trigger type. Supports filtering by contract and event name.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, preserve common line width (~80 symbols).

@@ -221,7 +235,6 @@ func (b *Block) GetExpectedBlockSizeWithoutTransactions(txCount int) int {
return size
}

// ToStackItem converts Block to stackitem.Item.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Useless change.

Comment on lines +59 to +66
type auxTrimmedBlockOut struct {
TxHashes []util.Uint256 `json:"tx"`
}

// auxTrimmedBlockIn is used for JSON i/o.
type auxTrimmedBlockIn struct {
TxHashes []json.RawMessage `json:"tx"`
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JSON marshallers are not needed for this structure. DecodeBinary is enough for our purposes.

return block, br.Err
}

func (b TrimmedBlock) MarshalJSON() ([]byte, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also should be removed, why do we need this code?

Copy link
Author

@lock9 lock9 Jan 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first, I considered adding a get trimmed block endpoint. I also had some issues to debug the RPC endpoints (it doesn't stop on the debugger). I had an error that I didn't know where it was coming from. Later I realized that it was due to the notification object serialization, not the block. The same for the 'toStackItem'. I didn't know if that was being used (now I know).

I also got confused because the tests 'were passing', when in practice, they weren't. I 'suspected' that this was related to some inner serilization / deserialization that I wasn't aware of. That's why I included these methods. I'll remove this and other parts that aren't being used.

return nil
}

func (b *TrimmedBlock) ToStackItem() stackitem.Item {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, remove it. We're only interested in proper deserialization from bytes.

@@ -18,3 +24,46 @@ func checkInt32(i int) error {
}
return nil
}

func (c notificationComparatorFilter) EventID() neorpc.EventID {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All exported methods require a comment.

@@ -18,3 +24,46 @@ func checkInt32(i int) error {
}
return nil
}

func (c notificationComparatorFilter) EventID() neorpc.EventID {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're trying to avoid util.go files as much as possible. Let's create a dedicated file for these structures and name this file accordingly.

@@ -18,3 +24,46 @@ func checkInt32(i int) error {
}
return nil
}

func (c notificationComparatorFilter) EventID() neorpc.EventID {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/notificationComparatorFilter/notificationEventComparator

@@ -18,3 +24,46 @@ func checkInt32(i int) error {
}
return nil
}

func (c notificationComparatorFilter) EventID() neorpc.EventID {
return c.id
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c.id field is not needed, remove it. notificatoinEventComparator works only with ContainedNotificatoinEvent, hence you may return neorpc.NotificationEventID here.

Container: container,
NotificationEvent: evt,
}
if filter == nil || rpcevent.Matches(&notificationComparatorFilter{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filter == nil check is excessive. rpcevent.Matche perfectly handle this case.

@AnnaShaleva
Copy link
Member

About trigger filters: I don't know/don't have an opinion.

Seems that we don't need it for now, so nothing should be done wrt this question.

@AnnaShaleva
Copy link
Member

Please, format commits according to https://github.com/nspcc-dev/.github/blob/master/git.md#commits. See https://github.com/nspcc-dev/neo-go/pull/3787/commits for example.

Also, please ensure your commits have valid signed-off-by signature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

API to fetch all notifications from a block (with filters)
3 participants