Merge pull request #2192 from nspcc-dev/rpc/container_hash
subscriptions: add container hash to notification event
This commit is contained in:
commit
e34c47a0c6
13 changed files with 137 additions and 41 deletions
|
@ -16,7 +16,7 @@ Currently supported events:
|
||||||
Contents: transaction. Filters: sender and signer.
|
Contents: transaction. Filters: sender and signer.
|
||||||
* notification generated during execution
|
* notification generated during execution
|
||||||
|
|
||||||
Contents: container hash, contract script hash, stack item. Filters: contract script hash.
|
Contents: container hash, contract hash, notification name, stack item. Filters: contract hash, notification name.
|
||||||
* transaction executed
|
* transaction executed
|
||||||
|
|
||||||
Contents: application execution result. Filters: VM state.
|
Contents: application execution result. Filters: VM state.
|
||||||
|
@ -284,10 +284,10 @@ Example:
|
||||||
|
|
||||||
### `notification_from_execution` notification
|
### `notification_from_execution` notification
|
||||||
|
|
||||||
Contains three parameters: contract script hash (hex-encoded LE Uint160
|
Contains four parameters: container hash (block's or transaction's hex-encoded LE
|
||||||
in a string), notification name and stack item (encoded the same way as
|
Uint256 hash in a string), contract hash (hex-encoded LE Uint160 in a string),
|
||||||
`state` field contents for notifications from `getapplicationlog`
|
notification name and stack item (encoded the same way as `state` field contents
|
||||||
response).
|
for notifications from `getapplicationlog` response).
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -329,6 +329,7 @@ Example:
|
||||||
},
|
},
|
||||||
"contract" : "0x1b4357bff5a01bdf2a6581247cf9ed1e24629176",
|
"contract" : "0x1b4357bff5a01bdf2a6581247cf9ed1e24629176",
|
||||||
"name" : "transfer",
|
"name" : "transfer",
|
||||||
|
"container" : "0xe1cd5e57e721d2a2e05fb1f08721b12057b25ab1dd7fd0f33ee1639932fdfad7",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
|
@ -413,7 +414,7 @@ func (chain *FakeChain) SubscribeForExecutions(ch chan<- *state.AppExecResult) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubscribeForNotifications implements Blockchainer interface.
|
// SubscribeForNotifications implements Blockchainer interface.
|
||||||
func (chain *FakeChain) SubscribeForNotifications(ch chan<- *state.NotificationEvent) {
|
func (chain *FakeChain) SubscribeForNotifications(ch chan<- *subscriptions.NotificationEvent) {
|
||||||
panic("TODO")
|
panic("TODO")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,7 +454,7 @@ func (chain *FakeChain) UnsubscribeFromExecutions(ch chan<- *state.AppExecResult
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnsubscribeFromNotifications implements Blockchainer interface.
|
// UnsubscribeFromNotifications implements Blockchainer interface.
|
||||||
func (chain *FakeChain) UnsubscribeFromNotifications(ch chan<- *state.NotificationEvent) {
|
func (chain *FakeChain) UnsubscribeFromNotifications(ch chan<- *subscriptions.NotificationEvent) {
|
||||||
panic("TODO")
|
panic("TODO")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||||
|
@ -647,7 +648,7 @@ func (bc *Blockchain) notificationDispatcher() {
|
||||||
// expected, but maps are convenient for adding/deleting elements).
|
// expected, but maps are convenient for adding/deleting elements).
|
||||||
blockFeed = make(map[chan<- *block.Block]bool)
|
blockFeed = make(map[chan<- *block.Block]bool)
|
||||||
txFeed = make(map[chan<- *transaction.Transaction]bool)
|
txFeed = make(map[chan<- *transaction.Transaction]bool)
|
||||||
notificationFeed = make(map[chan<- *state.NotificationEvent]bool)
|
notificationFeed = make(map[chan<- *subscriptions.NotificationEvent]bool)
|
||||||
executionFeed = make(map[chan<- *state.AppExecResult]bool)
|
executionFeed = make(map[chan<- *state.AppExecResult]bool)
|
||||||
)
|
)
|
||||||
for {
|
for {
|
||||||
|
@ -660,7 +661,7 @@ func (bc *Blockchain) notificationDispatcher() {
|
||||||
blockFeed[ch] = true
|
blockFeed[ch] = true
|
||||||
case chan<- *transaction.Transaction:
|
case chan<- *transaction.Transaction:
|
||||||
txFeed[ch] = true
|
txFeed[ch] = true
|
||||||
case chan<- *state.NotificationEvent:
|
case chan<- *subscriptions.NotificationEvent:
|
||||||
notificationFeed[ch] = true
|
notificationFeed[ch] = true
|
||||||
case chan<- *state.AppExecResult:
|
case chan<- *state.AppExecResult:
|
||||||
executionFeed[ch] = true
|
executionFeed[ch] = true
|
||||||
|
@ -673,7 +674,7 @@ func (bc *Blockchain) notificationDispatcher() {
|
||||||
delete(blockFeed, ch)
|
delete(blockFeed, ch)
|
||||||
case chan<- *transaction.Transaction:
|
case chan<- *transaction.Transaction:
|
||||||
delete(txFeed, ch)
|
delete(txFeed, ch)
|
||||||
case chan<- *state.NotificationEvent:
|
case chan<- *subscriptions.NotificationEvent:
|
||||||
delete(notificationFeed, ch)
|
delete(notificationFeed, ch)
|
||||||
case chan<- *state.AppExecResult:
|
case chan<- *state.AppExecResult:
|
||||||
delete(executionFeed, ch)
|
delete(executionFeed, ch)
|
||||||
|
@ -693,7 +694,10 @@ func (bc *Blockchain) notificationDispatcher() {
|
||||||
}
|
}
|
||||||
for i := range aer.Events {
|
for i := range aer.Events {
|
||||||
for ch := range notificationFeed {
|
for ch := range notificationFeed {
|
||||||
ch <- &aer.Events[i]
|
ch <- &subscriptions.NotificationEvent{
|
||||||
|
Container: aer.Container,
|
||||||
|
NotificationEvent: aer.Events[i],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,7 +714,10 @@ func (bc *Blockchain) notificationDispatcher() {
|
||||||
if aer.VMState == vm.HaltState {
|
if aer.VMState == vm.HaltState {
|
||||||
for i := range aer.Events {
|
for i := range aer.Events {
|
||||||
for ch := range notificationFeed {
|
for ch := range notificationFeed {
|
||||||
ch <- &aer.Events[i]
|
ch <- &subscriptions.NotificationEvent{
|
||||||
|
Container: aer.Container,
|
||||||
|
NotificationEvent: aer.Events[i],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -728,7 +735,10 @@ func (bc *Blockchain) notificationDispatcher() {
|
||||||
}
|
}
|
||||||
for i := range aer.Events {
|
for i := range aer.Events {
|
||||||
for ch := range notificationFeed {
|
for ch := range notificationFeed {
|
||||||
ch <- &aer.Events[i]
|
ch <- &subscriptions.NotificationEvent{
|
||||||
|
Container: aer.Container,
|
||||||
|
NotificationEvent: aer.Events[i],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1653,7 +1663,7 @@ func (bc *Blockchain) SubscribeForTransactions(ch chan<- *transaction.Transactio
|
||||||
// transactions use SubscribeForExecutions instead. Make sure this channel is
|
// transactions use SubscribeForExecutions instead. Make sure this channel is
|
||||||
// read from regularly as not reading these events might affect other Blockchain
|
// read from regularly as not reading these events might affect other Blockchain
|
||||||
// functions.
|
// functions.
|
||||||
func (bc *Blockchain) SubscribeForNotifications(ch chan<- *state.NotificationEvent) {
|
func (bc *Blockchain) SubscribeForNotifications(ch chan<- *subscriptions.NotificationEvent) {
|
||||||
bc.subCh <- ch
|
bc.subCh <- ch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1681,7 +1691,7 @@ func (bc *Blockchain) UnsubscribeFromTransactions(ch chan<- *transaction.Transac
|
||||||
// UnsubscribeFromNotifications unsubscribes given channel from new
|
// UnsubscribeFromNotifications unsubscribes given channel from new
|
||||||
// execution-generated notifications, you can close it afterwards. Passing
|
// execution-generated notifications, you can close it afterwards. Passing
|
||||||
// non-subscribed channel is a no-op.
|
// non-subscribed channel is a no-op.
|
||||||
func (bc *Blockchain) UnsubscribeFromNotifications(ch chan<- *state.NotificationEvent) {
|
func (bc *Blockchain) UnsubscribeFromNotifications(ch chan<- *subscriptions.NotificationEvent) {
|
||||||
bc.unsubCh <- ch
|
bc.unsubCh <- ch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||||
|
@ -1397,7 +1398,7 @@ func TestSubscriptions(t *testing.T) {
|
||||||
const chBufSize = 16
|
const chBufSize = 16
|
||||||
blockCh := make(chan *block.Block, chBufSize)
|
blockCh := make(chan *block.Block, chBufSize)
|
||||||
txCh := make(chan *transaction.Transaction, chBufSize)
|
txCh := make(chan *transaction.Transaction, chBufSize)
|
||||||
notificationCh := make(chan *state.NotificationEvent, chBufSize)
|
notificationCh := make(chan *subscriptions.NotificationEvent, chBufSize)
|
||||||
executionCh := make(chan *state.AppExecResult, chBufSize)
|
executionCh := make(chan *state.AppExecResult, chBufSize)
|
||||||
|
|
||||||
bc := newTestChain(t)
|
bc := newTestChain(t)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
|
@ -69,13 +70,13 @@ type Blockchainer interface {
|
||||||
SetNotary(mod services.Notary)
|
SetNotary(mod services.Notary)
|
||||||
SubscribeForBlocks(ch chan<- *block.Block)
|
SubscribeForBlocks(ch chan<- *block.Block)
|
||||||
SubscribeForExecutions(ch chan<- *state.AppExecResult)
|
SubscribeForExecutions(ch chan<- *state.AppExecResult)
|
||||||
SubscribeForNotifications(ch chan<- *state.NotificationEvent)
|
SubscribeForNotifications(ch chan<- *subscriptions.NotificationEvent)
|
||||||
SubscribeForTransactions(ch chan<- *transaction.Transaction)
|
SubscribeForTransactions(ch chan<- *transaction.Transaction)
|
||||||
VerifyTx(*transaction.Transaction) error
|
VerifyTx(*transaction.Transaction) error
|
||||||
VerifyWitness(util.Uint160, hash.Hashable, *transaction.Witness, int64) error
|
VerifyWitness(util.Uint160, hash.Hashable, *transaction.Witness, int64) error
|
||||||
GetMemPool() *mempool.Pool
|
GetMemPool() *mempool.Pool
|
||||||
UnsubscribeFromBlocks(ch chan<- *block.Block)
|
UnsubscribeFromBlocks(ch chan<- *block.Block)
|
||||||
UnsubscribeFromExecutions(ch chan<- *state.AppExecResult)
|
UnsubscribeFromExecutions(ch chan<- *state.AppExecResult)
|
||||||
UnsubscribeFromNotifications(ch chan<- *state.NotificationEvent)
|
UnsubscribeFromNotifications(ch chan<- *subscriptions.NotificationEvent)
|
||||||
UnsubscribeFromTransactions(ch chan<- *transaction.Transaction)
|
UnsubscribeFromTransactions(ch chan<- *transaction.Transaction)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,8 +39,8 @@ type WSClient struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notification represents server-generated notification for client subscriptions.
|
// Notification represents server-generated notification for client subscriptions.
|
||||||
// Value can be one of block.Block, state.AppExecResult, state.NotificationEvent
|
// Value can be one of block.Block, state.AppExecResult, subscriptions.NotificationEvent
|
||||||
// transaction.Transaction or response.NotaryRequestEvent based on Type.
|
// transaction.Transaction or subscriptions.NotaryRequestEvent based on Type.
|
||||||
type Notification struct {
|
type Notification struct {
|
||||||
Type response.EventID
|
Type response.EventID
|
||||||
Value interface{}
|
Value interface{}
|
||||||
|
@ -146,11 +147,11 @@ readloop:
|
||||||
case response.TransactionEventID:
|
case response.TransactionEventID:
|
||||||
val = &transaction.Transaction{}
|
val = &transaction.Transaction{}
|
||||||
case response.NotificationEventID:
|
case response.NotificationEventID:
|
||||||
val = new(state.NotificationEvent)
|
val = new(subscriptions.NotificationEvent)
|
||||||
case response.ExecutionEventID:
|
case response.ExecutionEventID:
|
||||||
val = new(state.AppExecResult)
|
val = new(state.AppExecResult)
|
||||||
case response.NotaryRequestEventID:
|
case response.NotaryRequestEventID:
|
||||||
val = new(response.NotaryRequestEvent)
|
val = new(subscriptions.NotaryRequestEvent)
|
||||||
case response.MissedEventID:
|
case response.MissedEventID:
|
||||||
// No value.
|
// No value.
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -118,7 +118,7 @@ func TestWSClientEvents(t *testing.T) {
|
||||||
// Events from RPC server test chain.
|
// Events from RPC server test chain.
|
||||||
var events = []string{
|
var events = []string{
|
||||||
`{"jsonrpc":"2.0","method":"transaction_executed","params":[{"container":"0xe1cd5e57e721d2a2e05fb1f08721b12057b25ab1dd7fd0f33ee1639932fdfad7","trigger":"Application","vmstate":"HALT","gasconsumed":"22910000","stack":[],"notifications":[{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","eventname":"contract call","state":{"type":"Array","value":[{"type":"ByteString","value":"dHJhbnNmZXI="},{"type":"Array","value":[{"type":"ByteString","value":"dpFiJB7t+XwkgWUq3xug9b9XQxs="},{"type":"ByteString","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"Integer","value":"1000"}]}]}},{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","eventname":"transfer","state":{"type":"Array","value":[{"type":"ByteString","value":"dpFiJB7t+XwkgWUq3xug9b9XQxs="},{"type":"ByteString","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"Integer","value":"1000"}]}}]}]}`,
|
`{"jsonrpc":"2.0","method":"transaction_executed","params":[{"container":"0xe1cd5e57e721d2a2e05fb1f08721b12057b25ab1dd7fd0f33ee1639932fdfad7","trigger":"Application","vmstate":"HALT","gasconsumed":"22910000","stack":[],"notifications":[{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","eventname":"contract call","state":{"type":"Array","value":[{"type":"ByteString","value":"dHJhbnNmZXI="},{"type":"Array","value":[{"type":"ByteString","value":"dpFiJB7t+XwkgWUq3xug9b9XQxs="},{"type":"ByteString","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"Integer","value":"1000"}]}]}},{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","eventname":"transfer","state":{"type":"Array","value":[{"type":"ByteString","value":"dpFiJB7t+XwkgWUq3xug9b9XQxs="},{"type":"ByteString","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"Integer","value":"1000"}]}}]}]}`,
|
||||||
`{"jsonrpc":"2.0","method":"notification_from_execution","params":[{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","eventname":"contract call","state":{"type":"Array","value":[{"type":"ByteString","value":"dHJhbnNmZXI="},{"type":"Array","value":[{"type":"ByteString","value":"dpFiJB7t+XwkgWUq3xug9b9XQxs="},{"type":"ByteString","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"Integer","value":"1000"}]}]}}]}`,
|
`{"jsonrpc":"2.0","method":"notification_from_execution","params":[{"container":"0xe1cd5e57e721d2a2e05fb1f08721b12057b25ab1dd7fd0f33ee1639932fdfad7","contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","eventname":"contract call","state":{"type":"Array","value":[{"type":"ByteString","value":"dHJhbnNmZXI="},{"type":"Array","value":[{"type":"ByteString","value":"dpFiJB7t+XwkgWUq3xug9b9XQxs="},{"type":"ByteString","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"Integer","value":"1000"}]}]}}]}`,
|
||||||
`{"jsonrpc":"2.0","method":"transaction_executed","params":[{"container":"0xf97a72b7722c109f909a8bc16c22368c5023d85828b09b127b237aace33cf099","trigger":"Application","vmstate":"HALT","gasconsumed":"6042610","stack":[],"notifications":[{"contract":"0xe65ff7b3a02d207b584a5c27057d4e9862ef01da","eventname":"contract call","state":{"type":"Array","value":[{"type":"ByteString","value":"dHJhbnNmZXI="},{"type":"Array","value":[{"type":"ByteString","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"ByteString","value":"IHKCdK+vw29DoHHTKM+j5inZy7A="},{"type":"Integer","value":"123"}]}]}},{"contract":"0xe65ff7b3a02d207b584a5c27057d4e9862ef01da","eventname":"transfer","state":{"type":"Array","value":[{"type":"ByteString","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"ByteString","value":"IHKCdK+vw29DoHHTKM+j5inZy7A="},{"type":"Integer","value":"123"}]}}]}]}`,
|
`{"jsonrpc":"2.0","method":"transaction_executed","params":[{"container":"0xf97a72b7722c109f909a8bc16c22368c5023d85828b09b127b237aace33cf099","trigger":"Application","vmstate":"HALT","gasconsumed":"6042610","stack":[],"notifications":[{"contract":"0xe65ff7b3a02d207b584a5c27057d4e9862ef01da","eventname":"contract call","state":{"type":"Array","value":[{"type":"ByteString","value":"dHJhbnNmZXI="},{"type":"Array","value":[{"type":"ByteString","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"ByteString","value":"IHKCdK+vw29DoHHTKM+j5inZy7A="},{"type":"Integer","value":"123"}]}]}},{"contract":"0xe65ff7b3a02d207b584a5c27057d4e9862ef01da","eventname":"transfer","state":{"type":"Array","value":[{"type":"ByteString","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"ByteString","value":"IHKCdK+vw29DoHHTKM+j5inZy7A="},{"type":"Integer","value":"123"}]}}]}]}`,
|
||||||
fmt.Sprintf(`{"jsonrpc":"2.0","method":"block_added","params":[%s]}`, b1Verbose),
|
fmt.Sprintf(`{"jsonrpc":"2.0","method":"block_added","params":[%s]}`, b1Verbose),
|
||||||
`{"jsonrpc":"2.0","method":"event_missed","params":[]}`,
|
`{"jsonrpc":"2.0","method":"event_missed","params":[]}`,
|
||||||
|
|
|
@ -3,21 +3,10 @@ package response
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/mempoolevent"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/network/payload"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// EventID represents an event type happening on the chain.
|
// EventID represents an event type happening on the chain.
|
||||||
EventID byte
|
type EventID byte
|
||||||
// NotaryRequestEvent represents P2PNotaryRequest event either added or removed
|
|
||||||
// from notary payload pool.
|
|
||||||
NotaryRequestEvent struct {
|
|
||||||
Type mempoolevent.Type `json:"type"`
|
|
||||||
NotaryRequest *payload.P2PNotaryRequest `json:"notaryrequest"`
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// InvalidEventID is an invalid event id that is the default value of
|
// InvalidEventID is an invalid event id that is the default value of
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package subscriptions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/mempoolevent"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/network/payload"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NotaryRequestEvent represents P2PNotaryRequest event either added or removed
|
||||||
|
// from notary payload pool.
|
||||||
|
type NotaryRequestEvent struct {
|
||||||
|
Type mempoolevent.Type `json:"type"`
|
||||||
|
NotaryRequest *payload.P2PNotaryRequest `json:"notaryrequest"`
|
||||||
|
}
|
56
pkg/rpc/response/result/subscriptions/notification_event.go
Normal file
56
pkg/rpc/response/result/subscriptions/notification_event.go
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
package subscriptions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NotificationEvent represents wrapper for notification from script execution.
|
||||||
|
type NotificationEvent struct {
|
||||||
|
// Container hash is the hash of script container which is either a block or a transaction.
|
||||||
|
Container util.Uint256
|
||||||
|
state.NotificationEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
// notificationEventAux is an auxiliary struct for JSON marshalling.
|
||||||
|
type notificationEventAux struct {
|
||||||
|
Container util.Uint256 `json:"container"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements implements json.Marshaler interface.
|
||||||
|
func (ne *NotificationEvent) MarshalJSON() ([]byte, error) {
|
||||||
|
h, err := json.Marshal(¬ificationEventAux{
|
||||||
|
Container: ne.Container,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to marshal hash: %w", err)
|
||||||
|
}
|
||||||
|
exec, err := json.Marshal(ne.NotificationEvent)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to marshal execution: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if h[len(h)-1] != '}' || exec[0] != '{' {
|
||||||
|
return nil, errors.New("can't merge internal jsons")
|
||||||
|
}
|
||||||
|
h[len(h)-1] = ','
|
||||||
|
h = append(h, exec[1:]...)
|
||||||
|
return h, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements implements json.Unmarshaler interface.
|
||||||
|
func (ne *NotificationEvent) UnmarshalJSON(data []byte) error {
|
||||||
|
aux := new(notificationEventAux)
|
||||||
|
if err := json.Unmarshal(data, aux); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(data, &ne.NotificationEvent); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ne.Container = aux.Container
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package subscriptions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/internal/testserdes"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNotificationEvent_MarshalUnmarshalJSON(t *testing.T) {
|
||||||
|
testserdes.MarshalUnmarshalJSON(t, &NotificationEvent{
|
||||||
|
Container: util.Uint256{1, 2, 3},
|
||||||
|
NotificationEvent: state.NotificationEvent{
|
||||||
|
ScriptHash: util.Uint160{4, 5, 6},
|
||||||
|
Name: "alarm",
|
||||||
|
Item: stackitem.NewArray([]stackitem.Item{stackitem.NewByteArray([]byte("qwerty"))}),
|
||||||
|
},
|
||||||
|
}, new(NotificationEvent))
|
||||||
|
}
|
|
@ -36,6 +36,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/services/oracle"
|
"github.com/nspcc-dev/neo-go/pkg/services/oracle"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/services/oracle/broadcaster"
|
"github.com/nspcc-dev/neo-go/pkg/services/oracle/broadcaster"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
|
@ -69,7 +70,7 @@ type (
|
||||||
notaryRequestSubs int
|
notaryRequestSubs int
|
||||||
blockCh chan *block.Block
|
blockCh chan *block.Block
|
||||||
executionCh chan *state.AppExecResult
|
executionCh chan *state.AppExecResult
|
||||||
notificationCh chan *state.NotificationEvent
|
notificationCh chan *subscriptions.NotificationEvent
|
||||||
transactionCh chan *transaction.Transaction
|
transactionCh chan *transaction.Transaction
|
||||||
notaryRequestCh chan mempoolevent.Event
|
notaryRequestCh chan mempoolevent.Event
|
||||||
}
|
}
|
||||||
|
@ -181,7 +182,7 @@ func New(chain blockchainer.Blockchainer, conf rpc.Config, coreServer *network.S
|
||||||
// These are NOT buffered to preserve original order of events.
|
// These are NOT buffered to preserve original order of events.
|
||||||
blockCh: make(chan *block.Block),
|
blockCh: make(chan *block.Block),
|
||||||
executionCh: make(chan *state.AppExecResult),
|
executionCh: make(chan *state.AppExecResult),
|
||||||
notificationCh: make(chan *state.NotificationEvent),
|
notificationCh: make(chan *subscriptions.NotificationEvent),
|
||||||
transactionCh: make(chan *transaction.Transaction),
|
transactionCh: make(chan *transaction.Transaction),
|
||||||
notaryRequestCh: make(chan mempoolevent.Event),
|
notaryRequestCh: make(chan mempoolevent.Event),
|
||||||
}
|
}
|
||||||
|
@ -1704,7 +1705,7 @@ chloop:
|
||||||
resp.Payload[0] = tx
|
resp.Payload[0] = tx
|
||||||
case e := <-s.notaryRequestCh:
|
case e := <-s.notaryRequestCh:
|
||||||
resp.Event = response.NotaryRequestEventID
|
resp.Event = response.NotaryRequestEventID
|
||||||
resp.Payload[0] = &response.NotaryRequestEvent{
|
resp.Payload[0] = &subscriptions.NotaryRequestEvent{
|
||||||
Type: e.Type,
|
Type: e.Type,
|
||||||
NotaryRequest: e.Data.(*payload.P2PNotaryRequest),
|
NotaryRequest: e.Data.(*payload.P2PNotaryRequest),
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions"
|
||||||
"go.uber.org/atomic"
|
"go.uber.org/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ func (f *feed) Matches(r *response.Notification) bool {
|
||||||
return senderOK && signerOK
|
return senderOK && signerOK
|
||||||
case response.NotificationEventID:
|
case response.NotificationEventID:
|
||||||
filt := f.filter.(request.NotificationFilter)
|
filt := f.filter.(request.NotificationFilter)
|
||||||
notification := r.Payload[0].(*state.NotificationEvent)
|
notification := r.Payload[0].(*subscriptions.NotificationEvent)
|
||||||
hashOk := filt.Contract == nil || notification.ScriptHash.Equals(*filt.Contract)
|
hashOk := filt.Contract == nil || notification.ScriptHash.Equals(*filt.Contract)
|
||||||
nameOk := filt.Name == nil || notification.Name == *filt.Name
|
nameOk := filt.Name == nil || notification.Name == *filt.Name
|
||||||
return hashOk && nameOk
|
return hashOk && nameOk
|
||||||
|
@ -82,7 +83,7 @@ func (f *feed) Matches(r *response.Notification) bool {
|
||||||
return applog.VMState.String() == filt.State
|
return applog.VMState.String() == filt.State
|
||||||
case response.NotaryRequestEventID:
|
case response.NotaryRequestEventID:
|
||||||
filt := f.filter.(request.TxFilter)
|
filt := f.filter.(request.TxFilter)
|
||||||
req := r.Payload[0].(*response.NotaryRequestEvent)
|
req := r.Payload[0].(*subscriptions.NotaryRequestEvent)
|
||||||
senderOk := filt.Sender == nil || req.NotaryRequest.FallbackTransaction.Signers[1].Account == *filt.Sender
|
senderOk := filt.Sender == nil || req.NotaryRequest.FallbackTransaction.Signers[1].Account == *filt.Sender
|
||||||
signerOK := true
|
signerOK := true
|
||||||
if filt.Signer != nil {
|
if filt.Signer != nil {
|
||||||
|
|
Loading…
Reference in a new issue