Skip to content

Commit

Permalink
Update support/contractevents to new ScVal interface
Browse files Browse the repository at this point in the history
  • Loading branch information
Shaptic committed Mar 22, 2023
1 parent 64f0a31 commit 5880ca8
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 108 deletions.
12 changes: 5 additions & 7 deletions support/contractevents/burn.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,17 @@ func (event *BurnEvent) parse(topics xdr.ScVec, value xdr.ScVal) error {
return ErrNotBurnEvent
}

rawFrom := topics[1]
from := parseAddress(&rawFrom)
if from == nil {
from, ok := topics[1].GetAddress()
if !ok {
return ErrNotBurnEvent
}

event.From = MustScAddressToString(from)

amount := parseAmount(&value)
if amount == nil {
amount, ok := value.GetI128()
if !ok {
return ErrNotBurnEvent
}
event.Amount = amount

event.Amount = *amount
return nil
}
8 changes: 1 addition & 7 deletions support/contractevents/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ var (
xdr.ScSymbol("burn"): EventTypeBurn,
}

// TODO: Finer-grained parsing errors
ErrNotStellarAssetContract = errors.New("event was not from a Stellar Asset Contract")
ErrEventUnsupported = errors.New("this type of Stellar Asset Contract event is unsupported")
ErrEventIntegrity = errors.New("contract ID doesn't match asset + passphrase")
Expand Down Expand Up @@ -99,12 +98,7 @@ func NewStellarAssetContractEvent(event *Event, networkPassphrase string) (Stell
// For all parsing errors, we just continue, since it's not a real error,
// just an event non-complaint with SAC events.
rawAsset := topics[len(topics)-1]
assetContainer, ok := rawAsset.GetObj()
if !ok || assetContainer == nil {
return evt, ErrNotStellarAssetContract
}

assetBytes, ok := assetContainer.GetBin()
assetBytes, ok := rawAsset.GetBytes()
if !ok || assetBytes == nil {
return evt, ErrNotStellarAssetContract
}
Expand Down
53 changes: 21 additions & 32 deletions support/contractevents/event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package contractevents

import (
"crypto/rand"
"encoding/base64"
"math"
"math/big"
"testing"
Expand Down Expand Up @@ -34,11 +33,7 @@ func TestScValCreators(t *testing.T) {
assert.EqualValues(t, *val.Sym, "hello")

val = makeAmount(1234)
obj, ok := val.GetObj()
assert.True(t, ok)
assert.NotNil(t, obj)

amt, ok := obj.GetI128()
amt, ok := val.GetI128()
assert.True(t, ok)
assert.EqualValues(t, 0, amt.Hi)
assert.EqualValues(t, 1234, amt.Lo)
Expand All @@ -52,11 +47,7 @@ func TestScValCreators(t *testing.T) {
Add(amount, big.NewInt(1234+4)) // now it's 2^66 + 1234

val = makeBigAmount(amount)
obj, ok = val.GetObj()
assert.True(t, ok)
assert.NotNil(t, obj)

amt, ok = obj.GetI128()
amt, ok = val.GetI128()
assert.True(t, ok)
assert.EqualValues(t, 4, amt.Hi)
assert.EqualValues(t, 1234, amt.Lo)
Expand Down Expand Up @@ -136,9 +127,10 @@ func TestSACTransferEvent(t *testing.T) {
// Ensure that invalid asset binaries are rejected
t.Run("bad asset binary", func(t *testing.T) {
resetEvent()
bsAsset := make([]byte, 42)
rand.Read(bsAsset)
(*baseXdrEvent.Body.V0.Topics[3].Obj).Bin = &bsAsset
rawBsAsset := make([]byte, 42)
rand.Read(rawBsAsset)
bsAsset := xdr.ScBytes(rawBsAsset)
baseXdrEvent.Body.V0.Topics[3].Bytes = &bsAsset
_, err = NewStellarAssetContractEvent(&baseXdrEvent, passphrase)
require.Error(t, err)
})
Expand Down Expand Up @@ -244,19 +236,20 @@ func TestFuzzingSACEventParser(t *testing.T) {
}
}

func TestRealXdr(t *testing.T) {
base64xdr := "AAAAAAAAAAGP097PJPXCcbtgOhu8wDc/ELPABxTdosN//YtrzxEJyAAAAAEAAAAAAAAABAAAAAUAAAAIdHJhbnNmZXIAAAAEAAAAAQAAAAgAAAAAAAAAAHN2/eiOTNYcwPspSheGs/HQYfXy8cpXRl+qkyIRuUbWAAAABAAAAAEAAAAIAAAAAAAAAAB4Ijl70f/hhiVmJftmpmXIoHZyUoyEiPSrpZAd5RfalwAAAAQAAAABAAAABgAAACVVU0QAOnN2/eiOTNYcwPspSheGs/HQYfXy8cpXRl+qkyIRuUbWAAAAAAAABAAAAAEAAAAFAAAAABHhowAAAAAAAAAAAA=="
// FIXME: This needs to be updated with real XDR once that's possible.
// func TestRealXdr(t *testing.T) {
// base64xdr := "AAAAAAAAAAGP097PJPXCcbtgOhu8wDc/ELPABxTdosN//YtrzxEJyAAAAAEAAAAAAAAABAAAAAUAAAAIdHJhbnNmZXIAAAAEAAAAAQAAAAgAAAAAAAAAAHN2/eiOTNYcwPspSheGs/HQYfXy8cpXRl+qkyIRuUbWAAAABAAAAAEAAAAIAAAAAAAAAAB4Ijl70f/hhiVmJftmpmXIoHZyUoyEiPSrpZAd5RfalwAAAAQAAAABAAAABgAAACVVU0QAOnN2/eiOTNYcwPspSheGs/HQYfXy8cpXRl+qkyIRuUbWAAAAAAAABAAAAAEAAAAFAAAAABHhowAAAAAAAAAAAA=="

rawXdr, err := base64.StdEncoding.DecodeString(base64xdr)
require.NoError(t, err)
// rawXdr, err := base64.StdEncoding.DecodeString(base64xdr)
// require.NoError(t, err)

event := xdr.ContractEvent{}
require.NoError(t, event.UnmarshalBinary(rawXdr))
// event := xdr.ContractEvent{}
// require.NoError(t, event.UnmarshalBinary(rawXdr))

parsed, err := NewStellarAssetContractEvent(&event, "Standalone Network ; February 2017")
assert.NoError(t, err)
assert.Equal(t, EventTypeTransfer, parsed.GetType())
}
// parsed, err := NewStellarAssetContractEvent(&event, "Standalone Network ; February 2017")
// assert.NoError(t, err)
// assert.Equal(t, EventTypeTransfer, parsed.GetType())
// }

//
// Test suite helpers below
Expand Down Expand Up @@ -286,14 +279,10 @@ func makeTransferTopic(asset xdr.Asset) xdr.ScVec {
contractStr := strkey.MustEncode(strkey.VersionByteContract, zeroContractHash[:])

return xdr.ScVec([]xdr.ScVal{
// event name
makeSymbol("transfer"),
// from
makeAddress(randomAccount),
// to
makeAddress(contractStr),
// asset details
makeAsset(asset),
makeSymbol("transfer"), // event name
makeAddress(randomAccount), // from
makeAddress(contractStr), // to
makeAsset(asset), // asset details
})
}

Expand Down
28 changes: 7 additions & 21 deletions support/contractevents/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,26 +127,17 @@ func makeBigAmount(amount *big.Int) xdr.ScVal {
hi := new(big.Int).Rsh(amount, 64)
lo := amount.And(amount, keepLower)

amountObj := &xdr.ScObject{
Type: xdr.ScObjectTypeScoI128,
return xdr.ScVal{
Type: xdr.ScValTypeScvI128,
I128: &xdr.Int128Parts{
Lo: xdr.Uint64(lo.Uint64()),
Hi: xdr.Uint64(hi.Uint64()),
},
}

return xdr.ScVal{
Type: xdr.ScValTypeScvObject,
Obj: &amountObj,
}
}

func makeAddress(address string) xdr.ScVal {
scAddress := xdr.ScAddress{}
scObject := &xdr.ScObject{
Type: xdr.ScObjectTypeScoAddress,
Address: &scAddress,
}

switch address[0] {
case 'C':
Expand All @@ -163,8 +154,8 @@ func makeAddress(address string) xdr.ScVal {
}

return xdr.ScVal{
Type: xdr.ScValTypeScvObject,
Obj: &scObject,
Type: xdr.ScValTypeScvAddress,
Address: &scAddress,
}
}

Expand Down Expand Up @@ -212,14 +203,9 @@ func makeAsset(asset xdr.Asset) xdr.ScVal {
panic("unexpected asset type")
}

slice := buffer.Bytes()
scObject := &xdr.ScObject{
Type: xdr.ScObjectTypeScoBytes,
Bin: &slice,
}

slice := xdr.ScBytes(buffer.Bytes())
return xdr.ScVal{
Type: xdr.ScValTypeScvObject,
Obj: &scObject,
Type: xdr.ScValTypeScvBytes,
Bytes: &slice,
}
}
63 changes: 22 additions & 41 deletions support/contractevents/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,15 @@ var ErrNotBalanceChangeEvent = errors.New("event doesn't represent a balance cha
// MustScAddressToString converts the low-level `xdr.ScAddress` union into the
// appropriate strkey (contract C... or account ID G...), panicking on any
// error. If the address is a nil pointer, this returns the empty string.
func MustScAddressToString(address *xdr.ScAddress) string {
func MustScAddressToString(address xdr.ScAddress) string {
str, err := ScAddressToString(address)
if err != nil {
panic(err)
}
return str
}

func ScAddressToString(address *xdr.ScAddress) (string, error) {
if address == nil {
return "", nil
}

func ScAddressToString(address xdr.ScAddress) (string, error) {
var result string
var err error

Expand All @@ -47,53 +43,38 @@ func ScAddressToString(address *xdr.ScAddress) (string, error) {
return result, nil
}

func parseAddress(val *xdr.ScVal) *xdr.ScAddress {
if val == nil {
return nil
}

address, ok := val.GetObj()
if !ok || address == nil || address.Type != xdr.ScObjectTypeScoAddress {
return nil
}

return address.Address
}

func parseAmount(val *xdr.ScVal) *xdr.Int128Parts {
valueObj, ok := val.GetObj()
if !ok || valueObj == nil || valueObj.Type != xdr.ScObjectTypeScoI128 {
return nil
}

return valueObj.I128
}

// parseBalanceChangeEvent is a generalization of a subset of the Stellar Asset
// Contract events. Transfer, mint, clawback, and burn events all have two
// addresses and an amount involved. The addresses represent different things in
// different event types (e.g. "from" or "admin"), but the parsing is identical.
// This helper extracts all three parts or returns a generic error if it can't.
func parseBalanceChangeEvent(topics xdr.ScVec, value xdr.ScVal) (string, string, xdr.Int128Parts, error) {
first, second, amount := "", "", xdr.Int128Parts{}

func parseBalanceChangeEvent(topics xdr.ScVec, value xdr.ScVal) (
first string,
second string,
amount xdr.Int128Parts,
err error,
) {
err = ErrNotBalanceChangeEvent
if len(topics) != 4 {
return first, second, amount, ErrNotBalanceChangeEvent
return
}

rawFirst, rawSecond := topics[1], topics[2]
firstSc, secondSc := parseAddress(&rawFirst), parseAddress(&rawSecond)
if firstSc == nil || secondSc == nil {
return first, second, amount, ErrNotBalanceChangeEvent
firstSc, ok := topics[1].GetAddress()
if !ok {
return
}
first = MustScAddressToString(firstSc)

first, second = MustScAddressToString(firstSc), MustScAddressToString(secondSc)
secondSc, ok := topics[2].GetAddress()
if !ok {
return
}
second = MustScAddressToString(secondSc)

amountPtr := parseAmount(&value)
if amountPtr == nil {
return first, second, amount, ErrNotBalanceChangeEvent
amount, ok = value.GetI128()
if !ok {
return
}

amount = *amountPtr
return first, second, amount, nil
}

0 comments on commit 5880ca8

Please sign in to comment.