Skip to content

Commit

Permalink
native: add committee change events
Browse files Browse the repository at this point in the history
Port neo-project/neo#3158.

Close #3326

Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
  • Loading branch information
AliceInHunterland committed Mar 15, 2024
1 parent bfc3aa6 commit 7a2e79e
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 0 deletions.
47 changes: 47 additions & 0 deletions pkg/core/native/native_neo.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ func newNEO(cfg config.ProtocolConfiguration) *NEO {
manifest.NewParameter("to", smartcontract.PublicKeyType),
manifest.NewParameter("amount", smartcontract.IntegerType),
)
n.AddEvent("CommitteeChanged",
manifest.NewParameter("old", smartcontract.ArrayType),
manifest.NewParameter("new", smartcontract.ArrayType),
)

return n
}
Expand Down Expand Up @@ -425,11 +429,54 @@ func (n *NEO) OnPersist(ic *interop.Context) error {
cache := ic.DAO.GetRWCache(n.ID).(*NeoCache)
// Cached newEpoch* values always have proper value set (either by PostPersist
// during the last epoch block handling or by initialization code).

// Extract previous committee public keys for comparison
prevCommitteePublicKeys := make([]*keys.PublicKey, len(cache.committee))
for i, member := range cache.committee {
pub, err := member.PublicKey()
if err != nil {
return fmt.Errorf("failed to get public key: %w", err)
}
prevCommitteePublicKeys[i] = pub
}
// Prepare for potential committee change
cache.nextValidators = cache.newEpochNextValidators
cache.committee = cache.newEpochCommittee
cache.committeeHash = cache.newEpochCommitteeHash
cache.votesChanged = false

// Extract new committee public keys for comparison
newCommitteePublicKeys := make([]*keys.PublicKey, len(cache.committee))
for i, member := range cache.committee {
pub, err := member.PublicKey()
if err != nil {
return fmt.Errorf("failed to get public key: %w", err)
}
newCommitteePublicKeys[i] = pub
}
// Check if the committee has changed by comparing public keys directly
committeeChanged := len(prevCommitteePublicKeys) != len(newCommitteePublicKeys)
for i := 0; i < len(prevCommitteePublicKeys) && !committeeChanged; i++ {
if !prevCommitteePublicKeys[i].Equal(newCommitteePublicKeys[i]) {
committeeChanged = true
}
}

// Notify subscribers if the committee has changed
if committeeChanged {
publicKeysToStackItems := func(publicKeys []*keys.PublicKey) []stackitem.Item {
items := make([]stackitem.Item, len(publicKeys))
for i, pubKey := range publicKeys {
items[i] = stackitem.NewByteArray(pubKey.Bytes())
}
return items
}
prevCommitteeStackItems := publicKeysToStackItems(prevCommitteePublicKeys)
newCommitteeStackItems := publicKeysToStackItems(newCommitteePublicKeys)
ic.AddNotification(n.Hash, "CommitteeChanged", stackitem.NewArray([]stackitem.Item{
stackitem.NewArray(prevCommitteeStackItems), stackitem.NewArray(newCommitteeStackItems),
}))
}
// We need to put in storage anyway, as it affects dumps
ic.DAO.PutStorageItem(n.ID, prefixCommittee, cache.committee.Bytes(ic.DAO.GetItemCtx()))
}
Expand Down
13 changes: 13 additions & 0 deletions pkg/core/native/native_test/neo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ func TestNEO_RegisterPriceCache(t *testing.T) {
}

func TestNEO_CandidateEvents(t *testing.T) {
neoCommitteeInvoker := newNeoCommitteeClient(t, 100_0000_0000)
neoValidatorsInvoker := neoCommitteeInvoker.WithSigners(neoCommitteeInvoker.Validator)
c := newNativeClient(t, nativenames.Neo)
singleSigner := c.Signers[0].(neotest.MultiSigner).Single(0)
cc := c.WithSigners(c.Signers[0], singleSigner)
Expand Down Expand Up @@ -116,6 +118,17 @@ func TestNEO_CandidateEvents(t *testing.T) {
tx = cc.Invoke(t, true, "unregisterCandidate", pkb)
aer = e.GetTxExecResult(t, tx)
require.Equal(t, 0, len(aer.Events))
neoValidatorsInvoker.AddNewBlock(t)
e.CheckHalt(t, tx, stackitem.Make(true))
e.CheckTxNotificationEvent(t, tx, 0, state.NotificationEvent{
ScriptHash: c.Hash,
Name: "CommitteeChanged",
Item: stackitem.NewArray([]stackitem.Item{
stackitem.NewByteArray(pkb),
stackitem.NewBool(true),
stackitem.Make(0),
}),
})
}

func TestNEO_Vote(t *testing.T) {
Expand Down
6 changes: 6 additions & 0 deletions pkg/rpcclient/neo/neo.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ type CandidateStateEvent struct {
Votes *big.Int
}

// CommitteeChangedEvent represents a CommitteeChanged NEO event.
type CommitteeChangedEvent struct {
Old []keys.PublicKey
New []keys.PublicKey
}

// VoteEvent represents a Vote NEO event.
type VoteEvent struct {
Account util.Uint160
Expand Down

0 comments on commit 7a2e79e

Please sign in to comment.