From af1aaa0969b2fe01a097948c33a367143e654b9b Mon Sep 17 00:00:00 2001 From: erika-sdf <92893480+erika-sdf@users.noreply.github.com> Date: Wed, 23 Mar 2022 14:15:52 -0700 Subject: [PATCH] Support new account fields for protocol-19. (#4294) --- protocols/horizon/main.go | 2 + .../horizon/internal/actions/account_test.go | 8 ++ .../horizon/internal/db2/history/accounts.go | 12 +- .../internal/db2/history/accounts_test.go | 18 ++- services/horizon/internal/db2/history/main.go | 2 + .../horizon/internal/db2/schema/bindata.go | 23 ++++ .../55_add_account_sequence_ledger.sql | 7 ++ .../internal/ingest/processor_runner_test.go | 3 + .../ingest/processors/accounts_processor.go | 7 +- .../processors/accounts_processor_test.go | 106 +++++++++++++++++- .../internal/resourceadapter/account_entry.go | 2 + .../resourceadapter/account_entry_test.go | 7 +- xdr/account_entry.go | 28 +++++ 13 files changed, 218 insertions(+), 7 deletions(-) create mode 100644 services/horizon/internal/db2/schema/migrations/55_add_account_sequence_ledger.sql diff --git a/protocols/horizon/main.go b/protocols/horizon/main.go index 41d4522e6c..cb2c744188 100644 --- a/protocols/horizon/main.go +++ b/protocols/horizon/main.go @@ -43,6 +43,8 @@ type Account struct { ID string `json:"id"` AccountID string `json:"account_id"` Sequence string `json:"sequence"` + SequenceLedger uint32 `json:"sequence_ledger,omitempty"` + SequenceTime string `json:"sequence_time,omitempty"` SubentryCount int32 `json:"subentry_count"` InflationDestination string `json:"inflation_destination,omitempty"` HomeDomain string `json:"home_domain,omitempty"` diff --git a/services/horizon/internal/actions/account_test.go b/services/horizon/internal/actions/account_test.go index 2d062f17a2..60f7f8b76f 100644 --- a/services/horizon/internal/actions/account_test.go +++ b/services/horizon/internal/actions/account_test.go @@ -32,6 +32,8 @@ var ( AccountID: accountOne, Balance: 20000, SequenceNumber: 223456789, + SequenceLedger: 2345, + SequenceTime: time.Unix(1647265533, 0), NumSubEntries: 10, Flags: 1, HomeDomain: "stellar.org", @@ -48,6 +50,8 @@ var ( AccountID: accountTwo, Balance: 50000, SequenceNumber: 648736, + SequenceLedger: 3456, + SequenceTime: time.Unix(1647365533, 0), NumSubEntries: 10, Flags: 2, HomeDomain: "meridian.stellar.org", @@ -64,6 +68,8 @@ var ( AccountID: signer, Balance: 50000, SequenceNumber: 648736, + SequenceLedger: 4567, + SequenceTime: time.Unix(1647465533, 0), NumSubEntries: 10, Flags: 2, MasterWeight: 5, @@ -170,6 +176,8 @@ func TestAccountInfo(t *testing.T) { AccountID: accountID, Balance: 9999999900, SequenceNumber: 8589934593, + SequenceLedger: 4567, + SequenceTime: time.Unix(1647465533, 0), NumSubEntries: 1, InflationDestination: "", HomeDomain: "", diff --git a/services/horizon/internal/db2/history/accounts.go b/services/horizon/internal/db2/history/accounts.go index 3f8b11dce6..43a38d295c 100644 --- a/services/horizon/internal/db2/history/accounts.go +++ b/services/horizon/internal/db2/history/accounts.go @@ -65,9 +65,9 @@ func (q *Q) GetAccountsByIDs(ctx context.Context, ids []string) ([]AccountEntry, // for each ledger with the current limits. func (q *Q) UpsertAccounts(ctx context.Context, accounts []AccountEntry) error { var accountID, inflationDestination, homeDomain, balance, buyingLiabilities, - sellingLiabilities, sequenceNumber, numSubEntries, flags, lastModifiedLedger, - numSponsored, numSponsoring, masterWeight, thresholdLow, thresholdMedium, - thresholdHigh, sponsor []interface{} + sellingLiabilities, sequenceNumber, sequenceLedger, sequenceTime, numSubEntries, + flags, lastModifiedLedger, numSponsored, numSponsoring, masterWeight, thresholdLow, + thresholdMedium, thresholdHigh, sponsor []interface{} for _, account := range accounts { accountID = append(accountID, account.AccountID) @@ -75,6 +75,8 @@ func (q *Q) UpsertAccounts(ctx context.Context, accounts []AccountEntry) error { buyingLiabilities = append(buyingLiabilities, account.BuyingLiabilities) sellingLiabilities = append(sellingLiabilities, account.SellingLiabilities) sequenceNumber = append(sequenceNumber, account.SequenceNumber) + sequenceLedger = append(sequenceLedger, account.SequenceLedger) + sequenceTime = append(sequenceTime, account.SequenceTime) numSubEntries = append(numSubEntries, account.NumSubEntries) inflationDestination = append(inflationDestination, account.InflationDestination) homeDomain = append(homeDomain, account.HomeDomain) @@ -95,6 +97,8 @@ func (q *Q) UpsertAccounts(ctx context.Context, accounts []AccountEntry) error { {"buying_liabilities", "bigint", buyingLiabilities}, {"selling_liabilities", "bigint", sellingLiabilities}, {"sequence_number", "bigint", sequenceNumber}, + {"sequence_ledger", "int", sequenceLedger}, + {"sequence_time", "timestamp", sequenceTime}, {"num_subentries", "int", numSubEntries}, {"inflation_destination", "text", inflationDestination}, {"flags", "int", flags}, @@ -270,6 +274,8 @@ var selectAccounts = sq.Select(` buying_liabilities, selling_liabilities, sequence_number, + sequence_ledger, + sequence_time, num_subentries, inflation_destination, flags, diff --git a/services/horizon/internal/db2/history/accounts_test.go b/services/horizon/internal/db2/history/accounts_test.go index bbd3c17ca0..8c36cdf5d2 100644 --- a/services/horizon/internal/db2/history/accounts_test.go +++ b/services/horizon/internal/db2/history/accounts_test.go @@ -2,6 +2,7 @@ package history import ( "testing" + "time" "github.com/guregu/null" "github.com/stellar/go/services/horizon/internal/db2" @@ -19,6 +20,8 @@ var ( AccountID: "GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB", Balance: 20000, SequenceNumber: 223456789, + SequenceLedger: 2345, + SequenceTime: time.Unix(1647265533, 0).UTC(), NumSubEntries: 10, InflationDestination: inflationDest, Flags: 1, @@ -36,6 +39,8 @@ var ( AccountID: "GCT2NQM5KJJEF55NPMY444C6M6CA7T33HRNCMA6ZFBIIXKNCRO6J25K7", Balance: 50000, SequenceNumber: 648736, + SequenceLedger: 3456, + SequenceTime: time.Unix(1647365533, 0).UTC(), NumSubEntries: 10, InflationDestination: inflationDest, Flags: 2, @@ -56,6 +61,8 @@ var ( AccountID: "GDPGOMFSP4IF7A4P7UBKA4UC4QTRLEHGBD6IMDIS3W3KBDNBFAQ7FXDY", Balance: 50000, SequenceNumber: 648736, + SequenceLedger: 4567, + SequenceTime: time.Unix(1647465533, 0).UTC(), NumSubEntries: 10, InflationDestination: inflationDest, Flags: 2, @@ -87,6 +94,10 @@ func TestInsertAccount(t *testing.T) { assert.Equal(t, "GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB", accounts[0].AccountID) assert.Equal(t, int64(20000), accounts[0].Balance) assert.Equal(t, int64(223456789), accounts[0].SequenceNumber) + assert.Equal(t, uint32(2345), accounts[0].SequenceLedger) + // Convert actual result to UTC timezone for comparison; + // query results from DB for SequenceTime supply a blank timezone. + assert.Equal(t, time.Unix(1647265533, 0).UTC(), accounts[0].SequenceTime.UTC()) assert.Equal(t, uint32(10), accounts[0].NumSubEntries) assert.Equal(t, "GBUH7T6U36DAVEKECMKN5YEBQYZVRBPNSZAAKBCO6P5HBMDFSQMQL4Z4", accounts[0].InflationDestination) assert.Equal(t, uint32(1), accounts[0].Flags) @@ -121,6 +132,7 @@ func TestUpsertAccount(t *testing.T) { AccountID: "GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB", Balance: 32847893, SequenceNumber: 223456789, + SequenceLedger: 2345, NumSubEntries: 10, InflationDestination: inflationDest, Flags: 1, @@ -156,6 +168,7 @@ func TestUpsertAccount(t *testing.T) { assert.NoError(t, err) assert.Len(t, accounts, 1) + accounts[0].SequenceTime = modifiedAccount.SequenceTime assert.Equal(t, modifiedAccount, accounts[0]) assert.Equal(t, uint32(1234), accounts[0].LastModifiedLedger) @@ -163,7 +176,9 @@ func TestUpsertAccount(t *testing.T) { assert.NoError(t, err) assert.Len(t, accounts, 1) - assert.Equal(t, account2, accounts[0]) + expectedAccount := account2 + expectedAccount.SequenceTime = accounts[0].SequenceTime + assert.Equal(t, expectedAccount, accounts[0]) assert.Equal(t, uint32(1235), accounts[0].LastModifiedLedger) } @@ -445,6 +460,7 @@ func TestGetAccountByID(t *testing.T) { assert.Equal(t, "GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB", resultAccount.AccountID) assert.Equal(t, int64(20000), resultAccount.Balance) assert.Equal(t, int64(223456789), resultAccount.SequenceNumber) + assert.Equal(t, uint32(2345), resultAccount.SequenceLedger) assert.Equal(t, uint32(10), resultAccount.NumSubEntries) assert.Equal(t, "GBUH7T6U36DAVEKECMKN5YEBQYZVRBPNSZAAKBCO6P5HBMDFSQMQL4Z4", resultAccount.InflationDestination) assert.Equal(t, uint32(1), resultAccount.Flags) diff --git a/services/horizon/internal/db2/history/main.go b/services/horizon/internal/db2/history/main.go index 1ab6f980ad..351b90538e 100644 --- a/services/horizon/internal/db2/history/main.go +++ b/services/horizon/internal/db2/history/main.go @@ -221,6 +221,8 @@ type AccountEntry struct { BuyingLiabilities int64 `db:"buying_liabilities"` SellingLiabilities int64 `db:"selling_liabilities"` SequenceNumber int64 `db:"sequence_number"` + SequenceLedger uint32 `db:"sequence_ledger"` + SequenceTime time.Time `db:"sequence_time"` NumSubEntries uint32 `db:"num_subentries"` InflationDestination string `db:"inflation_destination"` HomeDomain string `db:"home_domain"` diff --git a/services/horizon/internal/db2/schema/bindata.go b/services/horizon/internal/db2/schema/bindata.go index ed5b302615..22e9ee1392 100644 --- a/services/horizon/internal/db2/schema/bindata.go +++ b/services/horizon/internal/db2/schema/bindata.go @@ -50,6 +50,7 @@ // migrations/52_add_trade_type_index.sql (424B) // migrations/53_add_trades_rounding_slippage.sql (274B) // migrations/54_bigger_account_signers.sql (291B) +// migrations/55_add_account_sequence_ledger.sql (245B) // migrations/5_create_trades_table.sql (1.1kB) // migrations/6_create_assets_table.sql (366B) // migrations/7_modify_trades_table.sql (2.303kB) @@ -1124,6 +1125,26 @@ func migrations54_bigger_account_signersSql() (*asset, error) { return a, nil } +var _migrations55_add_account_sequence_ledgerSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd2\xd5\x55\xd0\xce\xcd\x4c\x2f\x4a\x2c\x49\x55\x08\x2d\xe0\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\x48\x4c\x4e\xce\x2f\xcd\x2b\x29\x56\x70\x74\x71\x51\x28\x4e\x2d\x2c\x4d\xcd\x4b\x4e\x8d\xcf\x49\x4d\x49\x4f\x2d\x52\xc8\xcc\x2b\x49\x05\xd1\x79\xa5\x39\x39\xd6\x44\x68\x2b\xc9\xcc\x4d\x55\x00\x11\xc5\x25\x89\xb9\x05\x0a\xe5\x99\x25\x19\xf9\xa5\x25\x60\x11\x85\xaa\xfc\xbc\x54\xa8\x41\x5c\xc8\xee\x71\xc9\x2f\xcf\xc3\x6e\xb4\x4b\x90\x7f\x00\xba\x93\x70\xb8\x02\x55\x29\xc8\x3e\x6b\x2e\x40\x00\x00\x00\xff\xff\x7d\x5b\x7a\x9d\xf5\x00\x00\x00") + +func migrations55_add_account_sequence_ledgerSqlBytes() ([]byte, error) { + return bindataRead( + _migrations55_add_account_sequence_ledgerSql, + "migrations/55_add_account_sequence_ledger.sql", + ) +} + +func migrations55_add_account_sequence_ledgerSql() (*asset, error) { + bytes, err := migrations55_add_account_sequence_ledgerSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "migrations/55_add_account_sequence_ledger.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9f, 0x27, 0x8e, 0x25, 0xd4, 0x6e, 0xe6, 0xd9, 0x9d, 0x9f, 0xfe, 0xe1, 0x1d, 0xb, 0x7d, 0x6c, 0x3b, 0xad, 0x9a, 0x34, 0x17, 0xc7, 0x2a, 0x24, 0x2b, 0x84, 0x75, 0x18, 0x8f, 0x95, 0x1e, 0x40}} + return a, nil +} + var _migrations5_create_trades_tableSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x94\x51\x6f\xaa\x40\x10\x85\xdf\xf9\x15\x13\x9f\x30\x17\x93\x7b\x6f\x5a\x5f\x4c\x9a\x58\x25\xad\xa9\xc1\xd6\x4a\xd2\x37\xb2\xb0\x23\x6c\xa2\x2c\x99\x1d\xda\xf0\xef\x1b\x68\x69\x10\x57\xad\xaf\x9c\x39\x67\x38\xbb\x5f\x76\x34\x82\x3f\x7b\x95\x92\x60\x84\xb0\x70\x66\x6b\x7f\xba\xf1\x61\x33\xbd\x5f\xfa\x90\x29\xc3\x9a\xaa\x88\x49\x48\x34\xe0\x3a\x00\xf0\xf3\x51\x17\x48\x82\x95\xce\x23\x25\x21\x56\xa9\xca\x19\x82\xd5\x06\x82\x70\xb9\xf4\x9a\xc9\x81\x26\x89\x34\x00\x95\x33\xa6\x48\x1d\xb5\x91\xf5\x76\x8b\x64\x35\x37\xb2\xc1\xdd\xee\x84\x5e\xcb\x71\x59\x9d\x75\xeb\x9d\x8c\x84\x31\xc8\x11\x57\x05\x42\x92\x09\x12\x09\x23\xc1\xbb\xa0\x4a\xe5\xa9\x3b\xbe\x19\xf6\x22\x3b\x1e\x65\x4c\x89\x64\x71\xdd\x8e\xcf\xb8\x12\x2d\x6d\x9b\xfe\xfd\xb7\x7b\xf6\xba\xcc\xb9\xff\xff\x30\x7b\xf4\x67\x4f\xe0\x76\x47\xee\xe0\xef\xf0\xbb\x57\xac\xcb\x34\xe3\x6b\x9b\x1d\xb8\xae\xe8\x76\xe0\xfb\x75\xbb\xd6\x75\xb6\xdf\xe1\x50\xdd\xd0\x19\x4e\x9c\x96\xbf\x30\x58\xbc\x84\x3e\x2c\x82\xb9\xff\x06\x19\x93\x8c\x0a\x25\x61\x15\xf4\x91\x0c\x5f\x17\xc1\x03\xc4\x4c\x88\xe0\xda\xc8\xf4\x5a\x0a\x3b\xe1\x9d\xd4\xb8\x8a\x1a\x0c\x2f\x45\xb7\xac\xda\x52\xea\x90\xfa\xb6\x2e\x65\xf4\x90\xf4\xfa\xe4\x78\xc7\x00\x9e\x5a\xf7\x75\x78\x97\x16\x1e\xb1\xe2\x1d\x5f\xa8\x67\x63\xa3\x5e\xdb\x7d\x17\xe6\xfa\x23\x77\xe6\xeb\xd5\xb3\xfd\x5d\x48\x84\x49\x84\xc4\x89\xf3\x19\x00\x00\xff\xff\x79\x87\x24\x6b\x4c\x04\x00\x00") func migrations5_create_trades_tableSqlBytes() ([]byte, error) { @@ -1385,6 +1406,7 @@ var _bindata = map[string]func() (*asset, error){ "migrations/52_add_trade_type_index.sql": migrations52_add_trade_type_indexSql, "migrations/53_add_trades_rounding_slippage.sql": migrations53_add_trades_rounding_slippageSql, "migrations/54_bigger_account_signers.sql": migrations54_bigger_account_signersSql, + "migrations/55_add_account_sequence_ledger.sql": migrations55_add_account_sequence_ledgerSql, "migrations/5_create_trades_table.sql": migrations5_create_trades_tableSql, "migrations/6_create_assets_table.sql": migrations6_create_assets_tableSql, "migrations/7_modify_trades_table.sql": migrations7_modify_trades_tableSql, @@ -1485,6 +1507,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ "52_add_trade_type_index.sql": &bintree{migrations52_add_trade_type_indexSql, map[string]*bintree{}}, "53_add_trades_rounding_slippage.sql": &bintree{migrations53_add_trades_rounding_slippageSql, map[string]*bintree{}}, "54_bigger_account_signers.sql": &bintree{migrations54_bigger_account_signersSql, map[string]*bintree{}}, + "55_add_account_sequence_ledger.sql": &bintree{migrations55_add_account_sequence_ledgerSql, map[string]*bintree{}}, "5_create_trades_table.sql": &bintree{migrations5_create_trades_tableSql, map[string]*bintree{}}, "6_create_assets_table.sql": &bintree{migrations6_create_assets_tableSql, map[string]*bintree{}}, "7_modify_trades_table.sql": &bintree{migrations7_modify_trades_tableSql, map[string]*bintree{}}, diff --git a/services/horizon/internal/db2/schema/migrations/55_add_account_sequence_ledger.sql b/services/horizon/internal/db2/schema/migrations/55_add_account_sequence_ledger.sql new file mode 100644 index 0000000000..b9a44a7b93 --- /dev/null +++ b/services/horizon/internal/db2/schema/migrations/55_add_account_sequence_ledger.sql @@ -0,0 +1,7 @@ +-- +migrate Up +ALTER TABLE accounts ADD sequence_ledger integer null; +ALTER TABLE accounts ADD sequence_time timestamp without time zone null; + +-- +migrate Down +ALTER TABLE accounts DROP sequence_ledger; +ALTER TABLE accounts DROP sequence_time; diff --git a/services/horizon/internal/ingest/processor_runner_test.go b/services/horizon/internal/ingest/processor_runner_test.go index c602f67aff..ae7383f7e1 100644 --- a/services/horizon/internal/ingest/processor_runner_test.go +++ b/services/horizon/internal/ingest/processor_runner_test.go @@ -5,6 +5,7 @@ import ( "io" "reflect" "testing" + "time" "github.com/guregu/null" "github.com/stretchr/testify/assert" @@ -29,6 +30,7 @@ func TestProcessorRunnerRunHistoryArchiveIngestionGenesis(t *testing.T) { AccountID: "GAAZI4TCR3TY5OJHCTJC2A4QSY6CJWJH5IAJTGKIN2ER7LBNVKOCCWN7", Balance: int64(1000000000000000000), SequenceNumber: 0, + SequenceTime: time.Unix(0, 0).UTC(), MasterWeight: 1, }, }).Return(nil).Once() @@ -94,6 +96,7 @@ func TestProcessorRunnerRunHistoryArchiveIngestionHistoryArchive(t *testing.T) { AccountID: "GAAZI4TCR3TY5OJHCTJC2A4QSY6CJWJH5IAJTGKIN2ER7LBNVKOCCWN7", Balance: int64(1000000000000000000), SequenceNumber: 0, + SequenceTime: time.Unix(0, 0).UTC(), MasterWeight: 1, }, }).Return(nil).Once() diff --git a/services/horizon/internal/ingest/processors/accounts_processor.go b/services/horizon/internal/ingest/processors/accounts_processor.go index 7ea97bc6f1..55fd5cac8b 100644 --- a/services/horizon/internal/ingest/processors/accounts_processor.go +++ b/services/horizon/internal/ingest/processors/accounts_processor.go @@ -2,11 +2,11 @@ package processors import ( "context" - "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/support/errors" "github.com/stellar/go/xdr" + "time" ) type AccountsProcessor struct { @@ -111,12 +111,17 @@ func (p *AccountsProcessor) ledgerEntryToRow(entry xdr.LedgerEntry) history.Acco inflationDestination = account.InflationDest.Address() } + seqTime := account.SeqTime() + seqLedger := account.SeqLedger() + return history.AccountEntry{ AccountID: account.AccountId.Address(), Balance: int64(account.Balance), BuyingLiabilities: int64(liabilities.Buying), SellingLiabilities: int64(liabilities.Selling), SequenceNumber: int64(account.SeqNum), + SequenceLedger: uint32(seqLedger), + SequenceTime: time.Unix(int64(seqTime), 0).UTC(), NumSubEntries: uint32(account.NumSubEntries), InflationDestination: inflationDestination, Flags: uint32(account.Flags), diff --git a/services/horizon/internal/ingest/processors/accounts_processor_test.go b/services/horizon/internal/ingest/processors/accounts_processor_test.go index ea9fe91125..9375f41341 100644 --- a/services/horizon/internal/ingest/processors/accounts_processor_test.go +++ b/services/horizon/internal/ingest/processors/accounts_processor_test.go @@ -5,6 +5,7 @@ package processors import ( "context" "testing" + "time" "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" @@ -47,6 +48,7 @@ func (s *AccountsProcessorTestSuiteState) TestCreatesAccounts() { { LastModifiedLedger: 123, AccountID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + SequenceTime: time.Unix(0, 0).UTC(), MasterWeight: 1, ThresholdLow: 1, ThresholdMedium: 1, @@ -150,13 +152,113 @@ func (s *AccountsProcessorTestSuiteLedger) TestNewAccount() { s.ctx, []history.AccountEntry{ { - LastModifiedLedger: 123, AccountID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + SequenceTime: time.Unix(0, 0).UTC(), + MasterWeight: 0, + ThresholdLow: 1, + ThresholdMedium: 2, + ThresholdHigh: 3, + HomeDomain: "stellar.org", + LastModifiedLedger: uint32(123), + }, + }, + ).Return(nil).Once() +} + +func (s *AccountsProcessorTestSuiteLedger) TestNewAccountWithExtension() { + account := xdr.AccountEntry{ + AccountId: xdr.MustAddress("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), + Thresholds: [4]byte{1, 1, 1, 1}, + Ext: xdr.AccountEntryExt{ + V: 1, + V1: &xdr.AccountEntryExtensionV1{ + Ext: xdr.AccountEntryExtensionV1Ext{ + V: 2, + V2: &xdr.AccountEntryExtensionV2{ + Ext: xdr.AccountEntryExtensionV2Ext{ + V: 3, + V3: &xdr.AccountEntryExtensionV3{ + SeqLedger: 2345, + SeqTime: 1647265533, + }, + }, + }, + }, + }, + }, + } + lastModifiedLedgerSeq := xdr.Uint32(123) + + err := s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeAccount, + Pre: nil, + Post: &xdr.LedgerEntry{ + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeAccount, + Account: &account, + }, + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + }, + }) + s.Assert().NoError(err) + + updatedAccount := xdr.AccountEntry{ + AccountId: xdr.MustAddress("GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML"), + Thresholds: [4]byte{0, 1, 2, 3}, + HomeDomain: "stellar.org", + Ext: xdr.AccountEntryExt{ + V: 1, + V1: &xdr.AccountEntryExtensionV1{ + Ext: xdr.AccountEntryExtensionV1Ext{ + V: 2, + V2: &xdr.AccountEntryExtensionV2{ + Ext: xdr.AccountEntryExtensionV2Ext{ + V: 3, + V3: &xdr.AccountEntryExtensionV3{ + SeqLedger: 2345, + SeqTime: 1647265533, + }, + }, + }, + }, + }, + }, + } + + err = s.processor.ProcessChange(s.ctx, ingest.Change{ + Type: xdr.LedgerEntryTypeAccount, + Pre: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq - 1, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeAccount, + Account: &account, + }, + }, + Post: &xdr.LedgerEntry{ + LastModifiedLedgerSeq: lastModifiedLedgerSeq, + Data: xdr.LedgerEntryData{ + Type: xdr.LedgerEntryTypeAccount, + Account: &updatedAccount, + }, + }, + }) + s.Assert().NoError(err) + + // We use LedgerEntryChangesCache so all changes are squashed + s.mockQ.On( + "UpsertAccounts", + s.ctx, + []history.AccountEntry{ + { + AccountID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + SequenceLedger: 2345, + SequenceTime: time.Unix(1647265533, 0).UTC(), MasterWeight: 0, ThresholdLow: 1, ThresholdMedium: 2, ThresholdHigh: 3, HomeDomain: "stellar.org", + LastModifiedLedger: uint32(123), }, }, ).Return(nil).Once() @@ -237,6 +339,7 @@ func (s *AccountsProcessorTestSuiteLedger) TestProcessUpgradeChange() { { LastModifiedLedger: uint32(lastModifiedLedgerSeq) + 1, AccountID: "GC3C4AKRBQLHOJ45U4XG35ESVWRDECWO5XLDGYADO6DPR3L7KIDVUMML", + SequenceTime: time.Unix(0, 0).UTC(), MasterWeight: 0, ThresholdLow: 1, ThresholdMedium: 2, @@ -302,6 +405,7 @@ func (s *AccountsProcessorTestSuiteLedger) TestFeeProcessedBeforeEverythingElse( LastModifiedLedger: 0, AccountID: "GAHK7EEG2WWHVKDNT4CEQFZGKF2LGDSW2IVM4S5DP42RBW3K6BTODB4A", Balance: 300, + SequenceTime: time.Unix(0, 0).UTC(), }, }, ).Return(nil).Once() diff --git a/services/horizon/internal/resourceadapter/account_entry.go b/services/horizon/internal/resourceadapter/account_entry.go index e18528be5b..f699988b6a 100644 --- a/services/horizon/internal/resourceadapter/account_entry.go +++ b/services/horizon/internal/resourceadapter/account_entry.go @@ -27,6 +27,8 @@ func PopulateAccountEntry( dest.PT = account.AccountID dest.AccountID = account.AccountID dest.Sequence = strconv.FormatInt(account.SequenceNumber, 10) + dest.SequenceLedger = account.SequenceLedger + dest.SequenceTime = fmt.Sprintf("%d", account.SequenceTime.Unix()) dest.SubentryCount = int32(account.NumSubEntries) dest.InflationDestination = account.InflationDestination dest.HomeDomain = account.HomeDomain diff --git a/services/horizon/internal/resourceadapter/account_entry_test.go b/services/horizon/internal/resourceadapter/account_entry_test.go index f74884edc4..092be3a19a 100644 --- a/services/horizon/internal/resourceadapter/account_entry_test.go +++ b/services/horizon/internal/resourceadapter/account_entry_test.go @@ -3,6 +3,7 @@ package resourceadapter import ( "encoding/base64" "encoding/json" + "fmt" "strconv" "testing" "time" @@ -44,6 +45,8 @@ var ( AccountID: accountID.Address(), Balance: 20000, SequenceNumber: 223456789, + SequenceLedger: 2345, + SequenceTime: time.Unix(1647265533, 0), NumSubEntries: 10, InflationDestination: inflationDest.Address(), Flags: 0b1001, // required and clawback @@ -143,7 +146,9 @@ func TestPopulateAccountEntry(t *testing.T) { tt.Equal(account.AccountID, hAccount.AccountID) tt.Equal(account.AccountID, hAccount.PT) tt.Equal(strconv.FormatInt(account.SequenceNumber, 10), hAccount.Sequence) - tt.Equal(int32(account.NumSubEntries), hAccount.SubentryCount) + tt.Equal(account.SequenceLedger, hAccount.SequenceLedger) + tt.Equal(fmt.Sprintf("%d", account.SequenceTime.Unix()), hAccount.SequenceTime) + tt.Equal(account.NumSubEntries, uint32(hAccount.SubentryCount)) tt.Equal(account.InflationDestination, hAccount.InflationDestination) tt.Equal(account.HomeDomain, hAccount.HomeDomain) tt.Equal(account.LastModifiedLedger, hAccount.LastModifiedLedger) diff --git a/xdr/account_entry.go b/xdr/account_entry.go index 41a0dd70bf..0649a71bb9 100644 --- a/xdr/account_entry.go +++ b/xdr/account_entry.go @@ -85,3 +85,31 @@ func (account *AccountEntry) SponsorPerSigner() map[string]AccountId { return signerToSponsor } + +func (account *AccountEntry) SeqTime() TimePoint { + v1, found := account.Ext.GetV1() + if found { + v2, foundV2 := v1.Ext.GetV2() + if foundV2 { + v, foundV3 := v2.Ext.GetV3() + if foundV3 { + return v.SeqTime + } + } + } + return 0 +} + +func (account *AccountEntry) SeqLedger() Uint32 { + v1, found := account.Ext.GetV1() + if found { + v2, foundV2 := v1.Ext.GetV2() + if foundV2 { + v, foundV3 := v2.Ext.GetV3() + if foundV3 { + return v.SeqLedger + } + } + } + return 0 +}