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

fix sac tests for preview 10 data model #4951

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/horizon.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ jobs:
env:
HORIZON_INTEGRATION_TESTS_ENABLED: true
HORIZON_INTEGRATION_TESTS_CORE_MAX_SUPPORTED_PROTOCOL: ${{ matrix.protocol-version }}
PROTOCOL_20_CORE_DEBIAN_PKG_VERSION: 19.11.1-1371.6c004ae12.focal~soroban
PROTOCOL_20_CORE_DOCKER_IMG: sreuland/stellar-core:19.11.1-1371.6c004ae12.focal-soroban
PROTOCOL_20_SOROBAN_RPC_DOCKER_IMG: sreuland/stellar-soroban-rpc:b18a52c085206
PROTOCOL_20_CORE_DEBIAN_PKG_VERSION: 19.11.1-1373.875f47e24.focal~soroban
PROTOCOL_20_CORE_DOCKER_IMG: sreuland/stellar-core:19.11.1-1373.875f47e24.focal-soroban
PROTOCOL_20_SOROBAN_RPC_DOCKER_IMG: sreuland/stellar-soroban-rpc:c584da283e24
PROTOCOL_19_CORE_DEBIAN_PKG_VERSION: 19.11.0-1323.7fb6d5e88.focal
PROTOCOL_19_CORE_DOCKER_IMG: stellar/stellar-core:19.11.0-1323.7fb6d5e88.focal
PGHOST: localhost
Expand Down
1 change: 0 additions & 1 deletion protocols/horizon/operations/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,6 @@ type InvokeHostFunction struct {
Base
Function string `json:"function"`
Parameters []HostFunctionParameter `json:"parameters"`
Type string `json:"type"`
Address string `json:"address"`
Salt string `json:"salt"`
AssetBalanceChanges []AssetContractBalanceChange `json:"asset_balance_changes"`
Expand Down
4 changes: 2 additions & 2 deletions services/horizon/internal/actions/operation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func TestInvokeHostFnDetailsInPaymentOperations(t *testing.T) {
1,
xdr.OperationTypeInvokeHostFunction,
[]byte(`{
"type": "invoke_contract",
"function": "HostFunctionTypeHostFunctionTypeInvokeContract",
"parameters": [
{
"value": "AAAADwAAAAdmbl9uYW1lAA==",
Expand Down Expand Up @@ -129,7 +129,7 @@ func TestInvokeHostFnDetailsInPaymentOperations(t *testing.T) {
tt.Assert.Len(records, 1)

op := records[0].(operations.InvokeHostFunction)
tt.Assert.Equal(op.Type, "invoke_contract")
tt.Assert.Equal(op.Function, "HostFunctionTypeHostFunctionTypeInvokeContract")
tt.Assert.Equal(len(op.Parameters), 2)
tt.Assert.Equal(op.Parameters[0].Value, "AAAADwAAAAdmbl9uYW1lAA==")
tt.Assert.Equal(op.Parameters[0].Type, "Sym")
Expand Down
221 changes: 181 additions & 40 deletions services/horizon/internal/ingest/processors/contract_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,27 @@ import (
"github.com/stellar/go/xdr"
)

const (
scDecimalPrecision = 7
)

var (
// https://github.com/stellar/rs-soroban-env/blob/v0.0.16/soroban-env-host/src/native_contract/token/public_types.rs#L22
nativeAssetSym = xdr.ScSymbol("Native")
// these are storage DataKey enum
// https://github.com/stellar/rs-soroban-env/blob/v0.0.16/soroban-env-host/src/native_contract/token/storage_types.rs#L23
balanceMetadataSym = xdr.ScSymbol("Balance")
metadataSym = xdr.ScSymbol("METADATA")
metadataNameSym = xdr.ScSymbol("name")
metadataSymbolSym = xdr.ScSymbol("symbol")
adminSym = xdr.ScSymbol("Admin")
issuerSym = xdr.ScSymbol("issuer")
assetCodeSym = xdr.ScSymbol("asset_code")
alphaNum4Sym = xdr.ScSymbol("AlphaNum4")
alphaNum12Sym = xdr.ScSymbol("AlphaNum12")
decimalSym = xdr.ScSymbol("decimal")
assetInfoSym = xdr.ScSymbol("AssetInfo")
decimalVal = xdr.Uint32(scDecimalPrecision)
assetInfoVec = &xdr.ScVec{
xdr.ScVal{
Type: xdr.ScValTypeScvSymbol,
Expand Down Expand Up @@ -43,7 +57,9 @@ var (
// https://github.com/stellar/rs-soroban-env/blob/v0.0.16/soroban-env-host/src/native_contract/token/asset_info.rs#L6
// https://github.com/stellar/rs-soroban-env/blob/v0.0.16/soroban-env-host/src/native_contract/token/contract.rs#L115
//
// The `ContractData` entry takes the following form:
// The asset info in `ContractData` entry takes the following form:
//
// - Instance storage - it's part of contract instance data storage
//
// - Key: a vector with one element, which is the symbol "AssetInfo"
//
Expand All @@ -52,26 +68,51 @@ var (
// - Value: a map with two key-value pairs: code and issuer
//
// ScVal{ Map: ScMap(
// { ScVal{ Sym: ScSymbol("asset_code") } -> ScVal{ Bytes: ScBytes(...) } },
// { ScVal{ Sym: ScSymbol("asset_code") } -> ScVal{ Str: ScString(...) } },
// { ScVal{ Sym: ScSymbol("issuer") } -> ScVal{ Bytes: ScBytes(...) } }
// )}
func AssetFromContractData(ledgerEntry xdr.LedgerEntry, passphrase string) *xdr.Asset {
contractData, ok := ledgerEntry.Data.GetContractData()
if !ok {
return nil
}
if contractData.Key.Type != xdr.ScValTypeScvLedgerKeyContractInstance ||
contractData.Body.BodyType != xdr.ContractEntryBodyTypeDataEntry {
return nil
}
contractInstanceData, ok := contractData.Body.Data.Val.GetInstance()
if !ok || contractInstanceData.Storage == nil {
return nil
}

// we don't support asset stats for lumens
nativeAssetContractID, err := xdr.MustNewNativeAsset().ContractID(passphrase)
if err != nil || (contractData.Contract.ContractId != nil && (*contractData.Contract.ContractId) == nativeAssetContractID) {
return nil
}

if !contractData.Key.Equals(assetInfoKey) {
var assetInfo *xdr.ScVal
for _, mapEntry := range *contractInstanceData.Storage {
if mapEntry.Key.Equals(assetInfoKey) {
// clone the map entry to avoid reference to loop iterator
mapValXdr, cloneErr := mapEntry.Val.MarshalBinary()
if cloneErr != nil {
return nil
}
assetInfo = &xdr.ScVal{}
cloneErr = assetInfo.UnmarshalBinary(mapValXdr)
if cloneErr != nil {
return nil
}
break
}
}

if assetInfo == nil {
return nil
}

vecPtr, ok := contractData.Body.Data.Val.GetVec()
vecPtr, ok := assetInfo.GetVec()
if !ok || vecPtr == nil || len(*vecPtr) != 2 {
return nil
}
Expand All @@ -96,23 +137,25 @@ func AssetFromContractData(ledgerEntry xdr.LedgerEntry, passphrase string) *xdr.
assetMap := *assetMapPtr

assetCodeEntry, assetIssuerEntry := assetMap[0], assetMap[1]
if sym, ok = assetCodeEntry.Key.GetSym(); !ok || sym != "asset_code" {
if sym, ok = assetCodeEntry.Key.GetSym(); !ok || sym != assetCodeSym {
return nil
}
assetCodeSc, ok := assetCodeEntry.Val.GetStr()
if !ok {
return nil
}
bin, ok := assetCodeEntry.Val.GetBytes()
if !ok || bin == nil {
if assetCode = string(assetCodeSc); assetCode == "" {
return nil
}
assetCode = string(bin)

if sym, ok = assetIssuerEntry.Key.GetSym(); !ok || sym != "issuer" {
if sym, ok = assetIssuerEntry.Key.GetSym(); !ok || sym != issuerSym {
return nil
}
bin, ok = assetIssuerEntry.Val.GetBytes()
if !ok || bin == nil {
assetIssuerSc, ok := assetIssuerEntry.Val.GetBytes()
if !ok {
return nil
}
assetIssuer, err = strkey.Encode(strkey.VersionByteAccountID, bin)
assetIssuer, err = strkey.Encode(strkey.VersionByteAccountID, assetIssuerSc)
if err != nil {
return nil
}
Expand Down Expand Up @@ -212,69 +255,159 @@ func ContractBalanceFromContractData(ledgerEntry xdr.LedgerEntry, passphrase str
return holder, amt, true
}

func metadataObjFromAsset(isNative bool, code, issuer string) (*xdr.ScVec, error) {
func metadataObjFromAsset(isNative bool, code, issuer string) (*xdr.ScMap, error) {
assetInfoVecKey := &xdr.ScVec{
xdr.ScVal{
Type: xdr.ScValTypeScvSymbol,
Sym: &assetInfoSym,
},
}

if isNative {
return &xdr.ScVec{
nativeVec := &xdr.ScVec{
xdr.ScVal{
Type: xdr.ScValTypeScvSymbol,
Sym: &nativeAssetSym,
},
}
return &xdr.ScMap{
xdr.ScMapEntry{
Key: xdr.ScVal{
Type: xdr.ScValTypeScvVec,
Vec: &assetInfoVecKey,
},
Val: xdr.ScVal{
Type: xdr.ScValTypeScvVec,
Vec: &nativeVec,
},
},
}, nil
}

var assetCodeLength int
var symbol xdr.ScSymbol
if len(code) <= 4 {
symbol = "AlphaNum4"
assetCodeLength = 4
} else {
symbol = "AlphaNum12"
assetCodeLength = 12
nameVal := xdr.ScString(code + ":" + issuer)
symbolVal := xdr.ScString(code)
metaDataMap := &xdr.ScMap{
xdr.ScMapEntry{
Key: xdr.ScVal{
Type: xdr.ScValTypeScvSymbol,
Sym: &decimalSym,
},
Val: xdr.ScVal{
Type: xdr.ScValTypeScvU32,
U32: &decimalVal,
},
},
xdr.ScMapEntry{
Key: xdr.ScVal{
Type: xdr.ScValTypeScvSymbol,
Sym: &metadataNameSym,
},
Val: xdr.ScVal{
Type: xdr.ScValTypeScvString,
Str: &nameVal,
},
},
xdr.ScMapEntry{
Key: xdr.ScVal{
Type: xdr.ScValTypeScvSymbol,
Sym: &metadataSymbolSym,
},
Val: xdr.ScVal{
Type: xdr.ScValTypeScvString,
Str: &symbolVal,
},
},
}

assetCodeSymbol := xdr.ScSymbol("asset_code")
assetCodeBytes := make([]byte, assetCodeLength)
copy(assetCodeBytes, code)
adminVec := &xdr.ScVec{
xdr.ScVal{
Type: xdr.ScValTypeScvSymbol,
Sym: &adminSym,
},
}

issuerSymbol := xdr.ScSymbol("issuer")
adminAccountId := xdr.MustAddress(issuer)
assetCodeVal := xdr.ScString(code)
issuerBytes, err := strkey.Decode(strkey.VersionByteAccountID, issuer)
if err != nil {
return nil, err
}

mapObj := &xdr.ScMap{
assetIssuerBytes := xdr.ScBytes(issuerBytes)
assetInfoMap := &xdr.ScMap{
xdr.ScMapEntry{
Key: xdr.ScVal{
Type: xdr.ScValTypeScvSymbol,
Sym: &assetCodeSymbol,
Sym: &assetCodeSym,
},
Val: xdr.ScVal{
Type: xdr.ScValTypeScvBytes,
Bytes: (*xdr.ScBytes)(&assetCodeBytes),
Type: xdr.ScValTypeScvString,
Str: &assetCodeVal,
},
},
xdr.ScMapEntry{
Key: xdr.ScVal{
Type: xdr.ScValTypeScvSymbol,
Sym: &issuerSymbol,
Sym: &issuerSym,
},
Val: xdr.ScVal{
Type: xdr.ScValTypeScvBytes,
Bytes: (*xdr.ScBytes)(&issuerBytes),
Bytes: &assetIssuerBytes,
},
},
}

return &xdr.ScVec{
alphaNumSym := alphaNum4Sym
if len(code) > 4 {
alphaNumSym = alphaNum12Sym
}
assetInfoVecVal := &xdr.ScVec{
xdr.ScVal{
Type: xdr.ScValTypeScvSymbol,
Sym: &symbol,
Sym: &alphaNumSym,
},
xdr.ScVal{
Type: xdr.ScValTypeScvMap,
Map: &mapObj,
Map: &assetInfoMap,
},
}, nil
}

storageMap := &xdr.ScMap{
xdr.ScMapEntry{
Key: xdr.ScVal{
Type: xdr.ScValTypeScvSymbol,
Sym: &metadataSym,
},
Val: xdr.ScVal{
Type: xdr.ScValTypeScvMap,
Map: &metaDataMap,
},
},
xdr.ScMapEntry{
Key: xdr.ScVal{
Type: xdr.ScValTypeScvVec,
Vec: &adminVec,
},
Val: xdr.ScVal{
Type: xdr.ScValTypeScvAddress,
Address: &xdr.ScAddress{
AccountId: &adminAccountId,
},
},
},
xdr.ScMapEntry{
Key: xdr.ScVal{
Type: xdr.ScValTypeScvVec,
Vec: &assetInfoVecKey,
},
Val: xdr.ScVal{
Type: xdr.ScValTypeScvVec,
Vec: &assetInfoVecVal,
},
},
}

return storageMap, nil
}

// AssetToContractData is the inverse of AssetFromContractData. It creates a
Expand All @@ -283,11 +416,12 @@ func metadataObjFromAsset(isNative bool, code, issuer string) (*xdr.ScVec, error
//
// Warning: Only for use in tests. This does not set a realistic expirationLedgerSeq
func AssetToContractData(isNative bool, code, issuer string, contractID [32]byte) (xdr.LedgerEntryData, error) {
vec, err := metadataObjFromAsset(isNative, code, issuer)
storageMap, err := metadataObjFromAsset(isNative, code, issuer)
if err != nil {
return xdr.LedgerEntryData{}, err
}
var ContractIDHash xdr.Hash = contractID

return xdr.LedgerEntryData{
Type: xdr.LedgerEntryTypeContractData,
ContractData: &xdr.ContractDataEntry{
Expand All @@ -296,14 +430,21 @@ func AssetToContractData(isNative bool, code, issuer string, contractID [32]byte
AccountId: nil,
ContractId: &ContractIDHash,
},
Key: assetInfoKey,
Key: xdr.ScVal{
Type: xdr.ScValTypeScvLedgerKeyContractInstance,
},
Durability: xdr.ContractDataDurabilityPersistent,
Body: xdr.ContractDataEntryBody{
BodyType: xdr.ContractEntryBodyTypeDataEntry,
Data: &xdr.ContractDataEntryData{
Val: xdr.ScVal{
Type: xdr.ScValTypeScvVec,
Vec: &vec,
Type: xdr.ScValTypeScvContractInstance,
Instance: &xdr.ScContractInstance{
Executable: xdr.ContractExecutable{
Type: xdr.ContractExecutableTypeContractExecutableToken,
},
Storage: storageMap,
},
},
// No flags written by the contract:
// https://github.com/stellar/rs-soroban-env/blob/c43bbd47959dde2e39eeeb5b7207868a44e96c7d/soroban-env-host/src/native_contract/token/asset_info.rs#L12
Expand Down
Loading