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

go-kosu: event emitter decoder #237

Merged
merged 2 commits into from Aug 27, 2019
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -0,0 +1,71 @@
package witness

import (
"errors"
"fmt"
"go-kosu/store"
"math/big"
)

// EventPosterRegistryUpdate represent a decoded PosterRegistryUpdate event
type EventPosterRegistryUpdate struct {
Amount *big.Int
Address store.Address
}

// EventValidatorRegistryUpdate represent a decoded ValidatorRegistryUpdate event
type EventValidatorRegistryUpdate struct {
Amount *big.Int
Address store.Address
PublicKey []byte
}

// DecodeKosuEvent tries to decode an EventEmitterKosuEvent from the Ethereum blockchain
func DecodeKosuEvent(ev *EventEmitterKosuEvent, t interface{}) error {
if ev.Data == nil {
return errors.New("data field is empty")
}

switch ev.EventType {
case "PosterRegistryUpdate":
dst, ok := t.(*EventPosterRegistryUpdate)
if !ok {
return fmt.Errorf("invalid type '%T' for PosterRegistryUpdate event", t)
}
return decodePosterRegistryUpdate(ev, dst)
case "ValidatorRegistryUpdate":
dst, ok := t.(*EventValidatorRegistryUpdate)
if !ok {
return fmt.Errorf("invalid type '%T' for ValidatorRegistryUpdate event", t)
}
return decodeValidatorRegistryUpdate(ev, dst)
}

return fmt.Errorf("don't know how to handle event '%s'", ev.EventType)
}

func newAddress(data [32]byte) (store.Address, error) {
return store.NewAddress(data[12:])
}

func decodePosterRegistryUpdate(ev *EventEmitterKosuEvent, dst *EventPosterRegistryUpdate) error {
address, err := newAddress(ev.Data[0])
if err != nil {
return err
}
dst.Address = address
dst.Amount = big.NewInt(0).SetBytes(ev.Data[1][:])

return nil
}

func decodeValidatorRegistryUpdate(ev *EventEmitterKosuEvent, dst *EventValidatorRegistryUpdate) error {
address, err := newAddress(ev.Data[1])
if err != nil {
return err
}
dst.Address = address
dst.PublicKey = ev.Data[0][:]
dst.Amount = big.NewInt(0).SetBytes(ev.Data[2][:])
return nil
}
@@ -0,0 +1,102 @@
// nolint:lll
package witness

import (
"encoding/hex"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

/*
Event sample:
&{
EventType:PosterRegistryUpdate,
Data:[
[0 0 0 0 0 0 0 0 0 0 0 0 197 33 244 131 246 7 235 94 164 214 178 223 219 213 64 19 71 83 168 101]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 53 201 173 197 222 160 0 0]
],
StringData: "",
Raw: {
Address:[47 58 254 255 9 20 243 55 105 205 251 243 252 248 112 195 59 38 195 17],
Topics:[
[189 100 126 158 46 239 23 47 63 222 199 104 53 130 154 36 250 133 178 140 109 116 199 22 231 232 165 200 126 191 198 131]
],
Data:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 96 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 160 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 80 111 115 116 101 114 82 101 103 105 115 116 114 121 85 112 100 97 116 101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 197 33 244 131 246 7 235 94 164 214 178 223 219 213 64 19 71 83 168 101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 53 201 173 197 222 160 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0],
BlockNumber:179,
TxHash:[254 44 32 185 99 231 19 3 49 66 107 150 41 50 126 209 225 171 83 37 91 202 130 213 197 171 220 249 25 175 158 185]
TxIndex:0
BlockHash:[137 33 85 47 221 52 12 204 168 235 214 187 95 58 253 82 202 49 113 33 29 230 25 58 32 196 120 188 1 208 50 96]
Index:1
Removed:false
}
}"
*/
func TestEventPosterRegistryUpdateDecoding(t *testing.T) {
newEvent := func() *EventEmitterKosuEvent {
return &EventEmitterKosuEvent{
EventType: "PosterRegistryUpdate",
Data: [][32]byte{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 33, 244, 131, 246, 7, 235, 94, 164, 214, 178, 223, 219, 213, 64, 19, 71, 83, 168, 101},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 53, 201, 173, 197, 222, 160, 0, 0},
},
}
}

t.Run("ValidEvent", func(t *testing.T) {
src := newEvent()
dst := &EventPosterRegistryUpdate{}

require.NoError(t,
DecodeKosuEvent(src, dst),
)

assert.Equal(t, "0xc521f483f607eb5ea4d6b2dfdbd540134753a865", dst.Address.String())
assert.Equal(t, "1000000000000000000000", dst.Amount.String())
})

t.Run("InvalidType", func(t *testing.T) {
src := newEvent()
dst := struct{}{}

require.Error(t,
DecodeKosuEvent(src, dst),
)
})
}

func TestEventValidatorRegistryUpdateDecoding(t *testing.T) {
newEvent := func() *EventEmitterKosuEvent {
return &EventEmitterKosuEvent{
EventType: "ValidatorRegistryUpdate",
Data: [][32]byte{
{222, 173, 190, 239},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 33, 244, 131, 246, 7, 235, 94, 164, 214, 178, 223, 219, 213, 64, 19, 71, 83, 168, 101},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 53, 201, 173, 197, 222, 160, 0, 0},
},
}
}

t.Run("ValidaEvent", func(t *testing.T) {
src := newEvent()
dst := &EventValidatorRegistryUpdate{}

require.NoError(t,
DecodeKosuEvent(src, dst),
)

assert.Equal(t, "deadbeef00000000000000000000000000000000000000000000000000000000", hex.EncodeToString(dst.PublicKey))
assert.Equal(t, "0xc521f483f607eb5ea4d6b2dfdbd540134753a865", dst.Address.String())
assert.Equal(t, "1000000000000000000000", dst.Amount.String())
})

t.Run("InvalidType", func(t *testing.T) {
src := newEvent()
dst := struct{}{}

require.Error(t,
DecodeKosuEvent(src, dst),
)
})
}
@@ -11,7 +11,6 @@ import (

"go-kosu/abci"
"go-kosu/abci/types"
"go-kosu/store"
)

// EventHandler is a callback that handles EventEmitterKosuEvent
@@ -161,17 +160,18 @@ func (w *Witness) broadcastTxSync(tx interface{}, args []interface{}) {
}

func (w *Witness) handlePosterRegistryUpdate(e *EventEmitterKosuEvent) {
// offset by 12 because the 20 byte address is packed into 32 bytes
address, err := store.NewAddress(e.Data[0][12:])
if err != nil {
w.log.Info("poster update event", "e", e)

event := &EventPosterRegistryUpdate{}
if err := DecodeKosuEvent(e, event); err != nil {
panic(err)
}

tx := &types.TransactionWitness{
Subject: types.TransactionWitness_POSTER,
Amount: types.NewBigInt(e.Data[1][:]),
Amount: types.NewBigInt(event.Amount.Bytes()),
Block: e.Raw.BlockNumber,
Address: address.String(),
Address: event.Address.String(),
}

w.broadcastTxSync(tx, []interface{}{
@@ -181,15 +181,19 @@ func (w *Witness) handlePosterRegistryUpdate(e *EventEmitterKosuEvent) {
}

func (w *Witness) handleValidatorRegistryUpdate(e *EventEmitterKosuEvent) {
// offset by 12 because the 20 byte address is packed into 32 bytes
address, _ := store.NewAddress(e.Data[1][12:])
w.log.Info("validator update event", "e", e)

event := &EventValidatorRegistryUpdate{}
if err := DecodeKosuEvent(e, event); err != nil {
panic(err)
}

tx := &types.TransactionWitness{
Subject: types.TransactionWitness_VALIDATOR,
Block: e.Raw.BlockNumber,
PublicKey: e.Data[0][:],
Address: address.String(),
Amount: types.NewBigInt(e.Data[2][:]),
PublicKey: event.PublicKey,
Address: event.Address.String(),
Amount: types.NewBigInt(event.Amount.Bytes()),
}

w.broadcastTxSync(tx, []interface{}{
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.