From 5880ca8f55c7bcf7865bc02d30c0820510d8572d Mon Sep 17 00:00:00 2001 From: George Kudrayvtsev Date: Mon, 20 Mar 2023 14:07:05 -0700 Subject: [PATCH] Update support/contractevents to new ScVal interface --- support/contractevents/burn.go | 12 +++--- support/contractevents/event.go | 8 +--- support/contractevents/event_test.go | 53 ++++++++++------------- support/contractevents/generate.go | 28 ++++--------- support/contractevents/utils.go | 63 ++++++++++------------------ 5 files changed, 56 insertions(+), 108 deletions(-) diff --git a/support/contractevents/burn.go b/support/contractevents/burn.go index 508f18bacb..11968ffc0f 100644 --- a/support/contractevents/burn.go +++ b/support/contractevents/burn.go @@ -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 } diff --git a/support/contractevents/event.go b/support/contractevents/event.go index c6bf9ab4f9..41ac92e672 100644 --- a/support/contractevents/event.go +++ b/support/contractevents/event.go @@ -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") @@ -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 } diff --git a/support/contractevents/event_test.go b/support/contractevents/event_test.go index 606982f8f7..e8ed9ebfc2 100644 --- a/support/contractevents/event_test.go +++ b/support/contractevents/event_test.go @@ -2,7 +2,6 @@ package contractevents import ( "crypto/rand" - "encoding/base64" "math" "math/big" "testing" @@ -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) @@ -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) @@ -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) }) @@ -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 @@ -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 }) } diff --git a/support/contractevents/generate.go b/support/contractevents/generate.go index b1e42c7341..e2d8254e51 100644 --- a/support/contractevents/generate.go +++ b/support/contractevents/generate.go @@ -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': @@ -163,8 +154,8 @@ func makeAddress(address string) xdr.ScVal { } return xdr.ScVal{ - Type: xdr.ScValTypeScvObject, - Obj: &scObject, + Type: xdr.ScValTypeScvAddress, + Address: &scAddress, } } @@ -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, } } diff --git a/support/contractevents/utils.go b/support/contractevents/utils.go index 18295b32ae..be849ab7bc 100644 --- a/support/contractevents/utils.go +++ b/support/contractevents/utils.go @@ -13,7 +13,7 @@ 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) @@ -21,11 +21,7 @@ func MustScAddressToString(address *xdr.ScAddress) string { 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 @@ -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 }