diff --git a/services/horizon/CHANGELOG.md b/services/horizon/CHANGELOG.md index 94f1d79973..d4f4c83811 100644 --- a/services/horizon/CHANGELOG.md +++ b/services/horizon/CHANGELOG.md @@ -11,6 +11,8 @@ This is the final release after the [release candidate](v2.17.0-release-candidat * `min_account_sequence_age` when it's `"0"`, as this is the default value when the condition is not set * `preconditions.ledgerbounds.max_ledger` when it's set to 0 (this means that there is no upper bound) +- Timebounds within the `preconditions` object are a string containing int64 UNIX timestamps in seconds rather than formatted date-times (which was a bug) ([4361](https://github.com/stellar/go/pull/4361)). + ## V2.17.0 Release Candidate **Upgrading to this version from <= v2.8.3 will trigger a state rebuild. During this process (which will take at least 10 minutes), Horizon will not ingest new ledgers.** diff --git a/services/horizon/internal/integration/transaction_preconditions_test.go b/services/horizon/internal/integration/transaction_preconditions_test.go index 13f29c59d6..44a6baac82 100644 --- a/services/horizon/internal/integration/transaction_preconditions_test.go +++ b/services/horizon/internal/integration/transaction_preconditions_test.go @@ -119,13 +119,23 @@ func TestTransactionPreconditionsTimeBounds(t *testing.T) { txHistory, err := itest.Client().TransactionDetail(tx.Hash) assert.NoError(t, err) - historyMaxTime, err := time.Parse(time.RFC3339, txHistory.Preconditions.TimeBounds.MaxTime) + + // Check that the deprecated string datetime fields match the new UNIX + // timestamp fields. + deprecatedHistoryMinTime, err := time.Parse(time.RFC3339, txHistory.ValidAfter) + assert.NoError(t, err) + deprecatedHistoryMaxTime, err := time.Parse(time.RFC3339, txHistory.ValidBefore) + assert.NoError(t, err) + + historyMinTime, err := strconv.ParseInt(txHistory.Preconditions.TimeBounds.MinTime, 10, 64) assert.NoError(t, err) - historyMinTime, err := time.Parse(time.RFC3339, txHistory.Preconditions.TimeBounds.MinTime) + historyMaxTime, err := strconv.ParseInt(txHistory.Preconditions.TimeBounds.MaxTime, 10, 64) assert.NoError(t, err) - assert.Equal(t, historyMaxTime.UTC().Unix(), txParams.Preconditions.TimeBounds.MaxTime) - assert.Equal(t, historyMinTime.UTC().Unix(), txParams.Preconditions.TimeBounds.MinTime) + assert.Equal(t, historyMinTime, deprecatedHistoryMinTime.UTC().Unix()) + assert.Equal(t, historyMaxTime, deprecatedHistoryMaxTime.UTC().Unix()) + assert.Equal(t, historyMinTime, txParams.Preconditions.TimeBounds.MinTime) + assert.Equal(t, historyMaxTime, txParams.Preconditions.TimeBounds.MaxTime) } func TestTransactionPreconditionsExtraSigners(t *testing.T) { diff --git a/services/horizon/internal/resourceadapter/transaction.go b/services/horizon/internal/resourceadapter/transaction.go index a72f202d36..547f8f4b40 100644 --- a/services/horizon/internal/resourceadapter/transaction.go +++ b/services/horizon/internal/resourceadapter/transaction.go @@ -4,6 +4,7 @@ import ( "context" "encoding/base64" "fmt" + "strconv" "time" "github.com/guregu/null" @@ -65,8 +66,8 @@ func PopulateTransaction( dest.ValidAfter = timeString(row.TimeBounds.Lower) dest.Preconditions.TimeBounds = &protocol.TransactionPreconditionsTimebounds{ - MaxTime: timeString(row.TimeBounds.Upper), - MinTime: timeString(row.TimeBounds.Lower), + MaxTime: timestampString(row.TimeBounds.Upper), + MinTime: timestampString(row.TimeBounds.Lower), } } @@ -158,3 +159,11 @@ func timeString(in null.Int) string { return time.Unix(in.Int64, 0).UTC().Format(time.RFC3339) } + +func timestampString(in null.Int) string { + if !in.Valid { + return "" + } + + return strconv.FormatInt(in.Int64, 10) +} diff --git a/services/horizon/internal/resourceadapter/transaction_test.go b/services/horizon/internal/resourceadapter/transaction_test.go index 9168f2c3e5..77246ae681 100644 --- a/services/horizon/internal/resourceadapter/transaction_test.go +++ b/services/horizon/internal/resourceadapter/transaction_test.go @@ -195,8 +195,8 @@ func TestPopulateTransaction_Preconditions(t *testing.T) { p := dest.Preconditions assert.Equal(t, validAfter.Format(time.RFC3339), dest.ValidAfter) assert.Equal(t, validBefore.Format(time.RFC3339), dest.ValidBefore) - assert.Equal(t, validAfter.Format(time.RFC3339), p.TimeBounds.MinTime) - assert.Equal(t, validBefore.Format(time.RFC3339), p.TimeBounds.MaxTime) + assert.Equal(t, fmt.Sprint(validAfter.Unix()), p.TimeBounds.MinTime) + assert.Equal(t, fmt.Sprint(validBefore.Unix()), p.TimeBounds.MaxTime) assert.Equal(t, minLedger, p.LedgerBounds.MinLedger) assert.Equal(t, maxLedger, p.LedgerBounds.MaxLedger) assert.Equal(t, fmt.Sprint(minAccountSequence), p.MinAccountSequence) @@ -289,8 +289,8 @@ func TestPopulateTransaction_PreconditionsV2(t *testing.T) { assert.NoError(t, PopulateTransaction(ctx, row.TransactionHash, &dest, row)) gotTimebounds := dest.Preconditions.TimeBounds - assert.Equal(t, "1970-01-01T00:00:05Z", gotTimebounds.MinTime) - assert.Equal(t, "1970-01-01T00:00:10Z", gotTimebounds.MaxTime) + assert.Equal(t, "5", gotTimebounds.MinTime) + assert.Equal(t, "10", gotTimebounds.MaxTime) } }