From 6ab328f7d7b7a111156c595ff15951853bb3364a Mon Sep 17 00:00:00 2001 From: Michael Buntarman Date: Tue, 31 Mar 2026 17:30:58 +0700 Subject: [PATCH 1/2] chore: restrict attestation to single-row actions only --- extensions/tn_utils/precompiles.go | 44 ++-- .../045-high-low-attestation-actions.sql | 188 +++++++++++++++++ .../attestation_date_range_test.go | 194 +++++++++++------- .../request_attestation_fee_test.go | 50 +++-- tests/streams/attestation/test_helpers.go | 2 +- 5 files changed, 365 insertions(+), 113 deletions(-) create mode 100644 internal/migrations/045-high-low-attestation-actions.sql diff --git a/extensions/tn_utils/precompiles.go b/extensions/tn_utils/precompiles.go index 9a131d96f..cb39af470 100644 --- a/extensions/tn_utils/precompiles.go +++ b/extensions/tn_utils/precompiles.go @@ -732,14 +732,13 @@ func forceLastArgFalseHandler(ctx *common.EngineContext, app *common.App, inputs // - 90 days of daily data = 90 rows, hourly = 2,160 rows (both safe) const MaxAttestationDateRangeSeconds int64 = 90 * 24 * 60 * 60 // 7,776,000 seconds -// validateAttestationDateRangeMethod checks that the date range in attestation -// query args does not exceed 90 days. Only applies to range-based actions -// (action_id 1-3: get_record, get_index, get_change_over_time) where args -// contain $from at index 2 and $to at index 3. -// -// Actions 4-5 (get_last_record, get_first_record) are single-point queries -// with LIMIT 1 and do not need date range validation. -// Actions 6-9 (binary) return a single boolean and are inherently safe. +// validateAttestationDateRangeMethod validates attestation action eligibility: +// - Actions 1-3 (get_record, get_index, get_change_over_time) are BLOCKED — they return +// multiple rows and are not allowed for attestation. +// - Actions 4-5 (get_last_record, get_first_record) are single-point (LIMIT 1) — no validation needed. +// - Actions 6-9 (binary) return a single boolean — no validation needed. +// - Actions 10-11 (get_high_value, get_low_value) are single-row range queries — date range +// validated (max 90 days, both from and to required). func validateAttestationDateRangeMethod() precompiles.Method { return precompiles.Method{ Name: "validate_attestation_date_range", @@ -759,10 +758,16 @@ func validateAttestationDateRangeHandler(ctx *common.EngineContext, app *common. return fmt.Errorf("action_id: %w", err) } - // Only validate range-based actions (1-3: get_record, get_index, get_change_over_time). - // Actions 4-5 are single-point (LIMIT 1), actions 6-9 are binary (single bool). - if actionID < 1 || actionID > 3 { - return nil // no validation needed + // Block multi-row actions entirely (IDs 1-3: get_record, get_index, get_change_over_time). + // These return arrays and are not allowed for attestation. + if actionID >= 1 && actionID <= 3 { + return fmt.Errorf("action %d not allowed for attestation: use get_last_record, get_first_record, get_high_value, get_low_value, or binary actions", actionID) + } + + // Only validate date range for range-based single-row actions (IDs 10-11: get_high_value, get_low_value). + // Actions 4-5 are single-point (LIMIT 1), actions 6-9 are binary (single bool) — no validation needed. + if actionID != 10 && actionID != 11 { + return nil } argsBytes, ok := inputs[1].([]byte) @@ -775,23 +780,18 @@ func validateAttestationDateRangeHandler(ctx *common.EngineContext, app *common. return fmt.Errorf("failed to decode action args: %w", err) } - // Range-based actions have signature: ($data_provider, $stream_id, $from, $to, ...) - // $from is at index 2, $to is at index 3 + // get_high_value/get_low_value signature: ($data_provider, $stream_id, $from, $to, $frozen_at) + // $from at index 2, $to at index 3 if len(args) < 4 { - return fmt.Errorf("range-based attestation action requires at least 4 args, got %d", len(args)) + return fmt.Errorf("attestation action requires at least 4 args, got %d", len(args)) } - // If both from and to are nil, the action returns the latest record (LIMIT 1) — safe fromVal := derefIntPtr(args[2]) toVal := derefIntPtr(args[3]) - if fromVal == nil && toVal == nil { - return nil - } - - // If only one is provided, the range is effectively unbounded — reject + // Both from and to are required for get_high_value/get_low_value (no "latest record" shortcut) if fromVal == nil || toVal == nil { - return fmt.Errorf("attestation queries with range-based actions (get_record, get_index, get_change_over_time) must specify both 'from' and 'to' parameters") + return fmt.Errorf("get_high_value/get_low_value attestation actions require both 'from' and 'to' parameters") } fromTS, err := toInt64(*fromVal) diff --git a/internal/migrations/045-high-low-attestation-actions.sql b/internal/migrations/045-high-low-attestation-actions.sql new file mode 100644 index 000000000..4ba5f91dc --- /dev/null +++ b/internal/migrations/045-high-low-attestation-actions.sql @@ -0,0 +1,188 @@ +/* + * HIGH/LOW ATTESTATION ACTIONS + * + * Adds get_high_value and get_low_value actions that return a single row + * (max or min value within a bounded date range). These are designed for + * attestation use cases where escrows need high/low price data. + * + * Both actions return exactly 1 row (LIMIT 1), making them safe for the + * attestation path. The precompile validates a max 90-day date range. + * + * Action IDs: + * 10 = get_high_value (max value in [from, to]) + * 11 = get_low_value (min value in [from, to]) + */ + +-- Register new actions in the attestation allowlist +INSERT INTO attestation_actions (action_name, action_id) VALUES ('get_high_value', 10) +ON CONFLICT (action_name) DO NOTHING; +INSERT INTO attestation_actions (action_name, action_id) VALUES ('get_low_value', 11) +ON CONFLICT (action_name) DO NOTHING; + +-- ============================================================================= +-- get_high_value_primitive: Returns the row with the highest value in [from, to] +-- ============================================================================= +CREATE OR REPLACE ACTION get_high_value_primitive( + $data_provider TEXT, + $stream_id TEXT, + $from INT8, + $to INT8, + $frozen_at INT8 +) PRIVATE VIEW RETURNS TABLE( + event_time INT8, + value NUMERIC(36,18) +) { + $data_provider := LOWER($data_provider); + $lower_caller TEXT := LOWER(@caller); + $stream_ref := get_stream_id($data_provider, $stream_id); + + IF $stream_ref IS NULL { + ERROR('Stream does not exist: data_provider=' || $data_provider || ' stream_id=' || $stream_id); + } + + if is_allowed_to_read_core($stream_ref, $lower_caller, $from, $to) == false { + ERROR('wallet not allowed to read'); + } + + $max_int8 INT8 := 9223372036854775000; + $effective_from INT8 := COALESCE($from, 0); + $effective_to INT8 := COALESCE($to, $max_int8); + $effective_frozen_at INT8 := COALESCE($frozen_at, $max_int8); + + RETURN WITH + deduped AS ( + SELECT pe.event_time, pe.value, + ROW_NUMBER() OVER ( + PARTITION BY pe.event_time + ORDER BY pe.created_at DESC + ) AS rn + FROM primitive_events pe + WHERE pe.stream_ref = $stream_ref + AND pe.event_time >= $effective_from + AND pe.event_time <= $effective_to + AND pe.created_at <= $effective_frozen_at + ) + SELECT event_time, value FROM deduped WHERE rn = 1 + ORDER BY value DESC, event_time ASC + LIMIT 1; +}; + +-- ============================================================================= +-- get_low_value_primitive: Returns the row with the lowest value in [from, to] +-- ============================================================================= +CREATE OR REPLACE ACTION get_low_value_primitive( + $data_provider TEXT, + $stream_id TEXT, + $from INT8, + $to INT8, + $frozen_at INT8 +) PRIVATE VIEW RETURNS TABLE( + event_time INT8, + value NUMERIC(36,18) +) { + $data_provider := LOWER($data_provider); + $lower_caller TEXT := LOWER(@caller); + $stream_ref := get_stream_id($data_provider, $stream_id); + + IF $stream_ref IS NULL { + ERROR('Stream does not exist: data_provider=' || $data_provider || ' stream_id=' || $stream_id); + } + + if is_allowed_to_read_core($stream_ref, $lower_caller, $from, $to) == false { + ERROR('wallet not allowed to read'); + } + + $max_int8 INT8 := 9223372036854775000; + $effective_from INT8 := COALESCE($from, 0); + $effective_to INT8 := COALESCE($to, $max_int8); + $effective_frozen_at INT8 := COALESCE($frozen_at, $max_int8); + + RETURN WITH + deduped AS ( + SELECT pe.event_time, pe.value, + ROW_NUMBER() OVER ( + PARTITION BY pe.event_time + ORDER BY pe.created_at DESC + ) AS rn + FROM primitive_events pe + WHERE pe.stream_ref = $stream_ref + AND pe.event_time >= $effective_from + AND pe.event_time <= $effective_to + AND pe.created_at <= $effective_frozen_at + ) + SELECT event_time, value FROM deduped WHERE rn = 1 + ORDER BY value ASC, event_time ASC + LIMIT 1; +}; + +-- ============================================================================= +-- get_high_value: Public facade — routes to primitive or composed +-- ============================================================================= +CREATE OR REPLACE ACTION get_high_value( + $data_provider TEXT, + $stream_id TEXT, + $from INT8, + $to INT8, + $frozen_at INT8 +) PUBLIC VIEW RETURNS TABLE( + event_time INT8, + value NUMERIC(36,18) +) { + $data_provider := LOWER($data_provider); + $is_primitive BOOL := is_primitive_stream($data_provider, $stream_id); + + if $is_primitive { + for $row in get_high_value_primitive($data_provider, $stream_id, $from, $to, $frozen_at) { + RETURN NEXT $row.event_time, $row.value; + } + } else { + -- For composed streams, iterate get_record results to find max value + $max_value NUMERIC(36,18) := NULL; + $max_event_time INT8 := NULL; + for $row in get_record($data_provider, $stream_id, $from, $to, $frozen_at, FALSE) { + if $max_value IS NULL OR $row.value > $max_value { + $max_value := $row.value; + $max_event_time := $row.event_time; + } + } + if $max_value IS NOT NULL { + RETURN NEXT $max_event_time, $max_value; + } + } +}; + +-- ============================================================================= +-- get_low_value: Public facade — routes to primitive or composed +-- ============================================================================= +CREATE OR REPLACE ACTION get_low_value( + $data_provider TEXT, + $stream_id TEXT, + $from INT8, + $to INT8, + $frozen_at INT8 +) PUBLIC VIEW RETURNS TABLE( + event_time INT8, + value NUMERIC(36,18) +) { + $data_provider := LOWER($data_provider); + $is_primitive BOOL := is_primitive_stream($data_provider, $stream_id); + + if $is_primitive { + for $row in get_low_value_primitive($data_provider, $stream_id, $from, $to, $frozen_at) { + RETURN NEXT $row.event_time, $row.value; + } + } else { + -- For composed streams, iterate get_record results to find min value + $min_value NUMERIC(36,18) := NULL; + $min_event_time INT8 := NULL; + for $row in get_record($data_provider, $stream_id, $from, $to, $frozen_at, FALSE) { + if $min_value IS NULL OR $row.value < $min_value { + $min_value := $row.value; + $min_event_time := $row.event_time; + } + } + if $min_value IS NOT NULL { + RETURN NEXT $min_event_time, $min_value; + } + } +}; diff --git a/tests/streams/attestation/attestation_date_range_test.go b/tests/streams/attestation/attestation_date_range_test.go index d79e827d1..b1b936905 100644 --- a/tests/streams/attestation/attestation_date_range_test.go +++ b/tests/streams/attestation/attestation_date_range_test.go @@ -59,27 +59,40 @@ func testAllDateRangeValidations(t *testing.T) func(ctx context.Context, platfor err = giveAttestationBalance(ctx, platform, systemAdmin.Address(), "1000000000000000000000") require.NoError(t, err) - // Insert a data point for binary action test + // Insert multiple data points for high/low tests err = insertTestDataPoint(ctx, platform, &systemAdmin, streamID, 1000000, "75.000000000000000000") require.NoError(t, err) + err = insertTestDataPoint(ctx, platform, &systemAdmin, streamID, 1000100, "120.000000000000000000") + require.NoError(t, err) + err = insertTestDataPoint(ctx, platform, &systemAdmin, streamID, 1000200, "30.000000000000000000") + require.NoError(t, err) + + // ===================================================================== + // Group 1: Actions 1-3 are BLOCKED from attestation + // ===================================================================== - // === Test 1: 30-day range should succeed === - t.Log("Test 1: get_record with 30-day range should succeed") + // === Test 1: get_record is blocked === + t.Log("Test 1: get_record is blocked from attestation") from30 := int64(1000000) to30 := int64(1000000 + 30*24*60*60) err = requestAttestationWithTimeRange(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_record", from30, to30) - require.NoError(t, err, "30-day range should succeed") - - // === Test 2: 180-day range should fail === - t.Log("Test 2: get_record with 180-day range should fail") - from180 := int64(1000000) - to180 := int64(1000000 + 180*24*60*60) - err = requestAttestationWithTimeRange(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_record", from180, to180) - require.Error(t, err, "180-day range should fail") - require.Contains(t, err.Error(), "exceeds maximum", "should mention exceeding maximum") - - // === Test 3: Both from and to nil should succeed (latest record, safe) === - t.Log("Test 3: get_record with both null dates should succeed") + require.Error(t, err, "get_record should be blocked") + require.Contains(t, err.Error(), "not allowed for attestation") + + // === Test 2: get_index is blocked === + t.Log("Test 2: get_index is blocked from attestation") + err = requestAttestationWithTimeRange(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_index", from30, to30) + require.Error(t, err, "get_index should be blocked") + require.Contains(t, err.Error(), "not allowed for attestation") + + // === Test 3: get_change_over_time is blocked === + t.Log("Test 3: get_change_over_time is blocked from attestation") + err = requestAttestationWithTimeRange(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_change_over_time", from30, to30) + require.Error(t, err, "get_change_over_time should be blocked") + require.Contains(t, err.Error(), "not allowed for attestation") + + // === Test 4: get_record with null dates is also blocked === + t.Log("Test 4: get_record with null dates is still blocked") nullArgs := []any{ systemAdmin.Address(), streamID, nil, nil, // from, to both nil @@ -88,91 +101,126 @@ func testAllDateRangeValidations(t *testing.T) func(ctx context.Context, platfor argsBytes, err := tn_utils.EncodeActionArgs(nullArgs) require.NoError(t, err) err = requestAttestationWithArgsBytes(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_record", argsBytes) - require.NoError(t, err, "both null dates should succeed (returns latest record)") + require.Error(t, err, "get_record should be blocked even with null dates") + require.Contains(t, err.Error(), "not allowed for attestation") - // === Test 4: Only one date param should fail (unbounded range) === - t.Log("Test 4: get_record with only 'to' should fail") - oneNullArgs := []any{ + // ===================================================================== + // Group 2: Actions 4-5 pass (single-point, LIMIT 1) + // ===================================================================== + + // === Test 5: get_last_record (action_id=4) passes === + t.Log("Test 5: get_last_record should pass (single-point query)") + lastRecordArgs := []any{ systemAdmin.Address(), streamID, - nil, int64(99999), // from=nil (unbounded), to=specified - nil, false, + nil, // before + nil, // frozen_at + false, // use_cache } - argsBytes, err = tn_utils.EncodeActionArgs(oneNullArgs) + argsBytes, err = tn_utils.EncodeActionArgs(lastRecordArgs) require.NoError(t, err) - err = requestAttestationWithArgsBytes(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_record", argsBytes) - require.Error(t, err, "one null date should fail") - require.Contains(t, err.Error(), "must specify both", "should require both from and to") - - // === Test 5: Exactly 90 days should succeed (boundary) === - t.Log("Test 5: get_record with exactly 90-day range should succeed") - from90 := int64(1000000) - to90 := int64(1000000 + 90*24*60*60) - err = requestAttestationWithTimeRange(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_record", from90, to90) - require.NoError(t, err, "exactly 90-day range should succeed") + err = requestAttestationWithArgsBytes(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_last_record", argsBytes) + require.NoError(t, err, "get_last_record should pass") - // === Test 6: 91 days should fail (just over boundary) === - t.Log("Test 6: get_record with 91-day range should fail") - from91 := int64(1000000) - to91 := int64(1000000 + 91*24*60*60) - err = requestAttestationWithTimeRange(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_record", from91, to91) - require.Error(t, err, "91-day range should fail") - require.Contains(t, err.Error(), "exceeds maximum") + // ===================================================================== + // Group 3: Actions 6-9 pass (binary, single boolean) + // ===================================================================== - // === Test 7: Binary action (price_above_threshold) skips validation === - t.Log("Test 7: binary action should skip date range validation") + // === Test 6: binary action (price_above_threshold) passes === + t.Log("Test 6: binary action should pass") thresholdVal, err := kwilTypes.ParseDecimal("50.000000000000000000") require.NoError(t, err) thresholdVal.SetPrecisionAndScale(36, 18) binaryArgs := []any{ systemAdmin.Address(), streamID, int64(1000000), // timestamp - thresholdVal, // threshold as NUMERIC(36,18) + thresholdVal, // threshold nil, // frozen_at } argsBytes, err = tn_utils.EncodeActionArgs(binaryArgs) require.NoError(t, err) err = requestAttestationWithArgsBytes(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "price_above_threshold", argsBytes) - require.NoError(t, err, "binary action should skip date range validation") + require.NoError(t, err, "binary action should pass") - // === Test 8: get_index with 180-day range should also fail === - t.Log("Test 8: get_index with 180-day range should fail") - err = requestAttestationWithTimeRange(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_index", from180, to180) - require.Error(t, err, "get_index with 180-day range should fail") - require.Contains(t, err.Error(), "exceeds maximum") + // ===================================================================== + // Group 4: Actions 10-11 date range validation + // ===================================================================== + + // === Test 7: get_high_value with valid 30-day range succeeds === + t.Log("Test 7: get_high_value with valid range should succeed") + highArgs := []any{ + systemAdmin.Address(), streamID, + int64(900000), int64(1100000), // ~1.2 day range + nil, // frozen_at + } + argsBytes, err = tn_utils.EncodeActionArgs(highArgs) + require.NoError(t, err) + err = requestAttestationWithArgsBytes(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_high_value", argsBytes) + require.NoError(t, err, "get_high_value with valid range should succeed") + + // === Test 8: get_low_value with valid range succeeds === + t.Log("Test 8: get_low_value with valid range should succeed") + lowArgs := []any{ + systemAdmin.Address(), streamID, + int64(900000), int64(1100000), + nil, + } + argsBytes, err = tn_utils.EncodeActionArgs(lowArgs) + require.NoError(t, err) + err = requestAttestationWithArgsBytes(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_low_value", argsBytes) + require.NoError(t, err, "get_low_value with valid range should succeed") - // === Test 8b: get_change_over_time with 180-day range should also fail === - t.Log("Test 8b: get_change_over_time with 180-day range should fail") - err = requestAttestationWithTimeRange(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_change_over_time", from180, to180) - require.Error(t, err, "get_change_over_time with 180-day range should fail") + // === Test 9: get_high_value with 180-day range fails === + t.Log("Test 9: get_high_value with 180-day range should fail") + highLongArgs := []any{ + systemAdmin.Address(), streamID, + int64(1000000), int64(1000000 + 180*24*60*60), + nil, + } + argsBytes, err = tn_utils.EncodeActionArgs(highLongArgs) + require.NoError(t, err) + err = requestAttestationWithArgsBytes(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_high_value", argsBytes) + require.Error(t, err, "get_high_value with 180-day range should fail") require.Contains(t, err.Error(), "exceeds maximum") - // === Test 9: get_last_record (action_id=4) should skip validation === - // Signature: get_last_record($data_provider TEXT, $stream_id TEXT, $before INT8, $frozen_at INT8, $use_cache BOOL) - t.Log("Test 9: get_last_record should skip date range validation") - lastRecordArgs := []any{ + // === Test 10: get_high_value with from > to fails === + t.Log("Test 10: get_high_value with from > to should fail") + highInvertedArgs := []any{ systemAdmin.Address(), streamID, - nil, // before - nil, // frozen_at - false, // use_cache + int64(2000000), int64(1000000), + nil, } - argsBytes, err = tn_utils.EncodeActionArgs(lastRecordArgs) + argsBytes, err = tn_utils.EncodeActionArgs(highInvertedArgs) require.NoError(t, err) - err = requestAttestationWithArgsBytes(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_last_record", argsBytes) - require.NoError(t, err, "get_last_record should skip date range validation") + err = requestAttestationWithArgsBytes(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_high_value", argsBytes) + require.Error(t, err, "inverted range should fail") + require.Contains(t, err.Error(), "must be less than or equal") - // === Test 10: from == to (single-point query, dateRange=0) should succeed === - t.Log("Test 10: get_record with from == to should succeed") - samePoint := int64(1000000) - err = requestAttestationWithTimeRange(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_record", samePoint, samePoint) - require.NoError(t, err, "single-point query (from == to) should succeed") + // === Test 11: get_high_value with nil from/to fails === + t.Log("Test 11: get_high_value with nil dates should fail") + highNilArgs := []any{ + systemAdmin.Address(), streamID, + nil, nil, + nil, + } + argsBytes, err = tn_utils.EncodeActionArgs(highNilArgs) + require.NoError(t, err) + err = requestAttestationWithArgsBytes(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_high_value", argsBytes) + require.Error(t, err, "get_high_value with nil dates should fail") + require.Contains(t, err.Error(), "require both") - // === Test 11: from > to (negative range) should fail === - t.Log("Test 11: get_record with from > to should fail") - err = requestAttestationWithTimeRange(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_record", int64(2000000), int64(1000000)) - require.Error(t, err, "negative range (from > to) should fail") - require.Contains(t, err.Error(), "must be less than or equal", "should reject inverted range") + // === Test 12: get_high_value with exactly 90 days succeeds === + t.Log("Test 12: get_high_value with exactly 90-day range should succeed") + high90Args := []any{ + systemAdmin.Address(), streamID, + int64(1000000), int64(1000000 + 90*24*60*60), + nil, + } + argsBytes, err = tn_utils.EncodeActionArgs(high90Args) + require.NoError(t, err) + err = requestAttestationWithArgsBytes(ctx, platform, &systemAdmin, systemAdmin.Address(), streamID, "get_high_value", argsBytes) + require.NoError(t, err, "exactly 90-day range should succeed") - t.Log("All date range validation tests passed") + t.Log("All attestation restriction tests passed") return nil } } diff --git a/tests/streams/attestation/request_attestation_fee_test.go b/tests/streams/attestation/request_attestation_fee_test.go index 80989c81b..9e2c8d56f 100644 --- a/tests/streams/attestation/request_attestation_fee_test.go +++ b/tests/streams/attestation/request_attestation_fee_test.go @@ -81,8 +81,8 @@ func setupAttestationTestEnvironment(t *testing.T) func(ctx context.Context, pla return fmt.Errorf("failed to register system admin as data provider: %w", err) } - // Note: get_record is already registered in 023-attestation-schema.sql with ID=1 - // No need to register it again + // Note: get_last_record (ID=4) and get_high_value (ID=10) are registered in + // 023-attestation-schema.sql and 045-high-low-attestation-actions.sql respectively // Create a test stream for attestations streamID := "st000000000000000000000000000000" @@ -120,7 +120,7 @@ func testAttestationNetworkWriterPaysFee(t *testing.T) func(ctx context.Context, // Request attestation (should pay 40 TRUF as non-exempt user) systemAdmin := util.Unsafe_NewEthereumAddressFromString("0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf") streamID := "st000000000000000000000000000000" - err = requestAttestation(ctx, platform, requesterAddr, systemAdmin.Address(), streamID, "get_record") + err = requestAttestation(ctx, platform, requesterAddr, systemAdmin.Address(), streamID, "get_last_record") require.NoError(t, err, "attestation request should succeed") // Verify balance decreased by 40 TRUF @@ -148,7 +148,7 @@ func testAttestationInsufficientBalance(t *testing.T) func(ctx context.Context, // Try to request attestation (should fail) systemAdmin := util.Unsafe_NewEthereumAddressFromString("0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf") streamID := "st000000000000000000000000000000" - err = requestAttestation(ctx, platform, requesterAddr, systemAdmin.Address(), streamID, "get_record") + err = requestAttestation(ctx, platform, requesterAddr, systemAdmin.Address(), streamID, "get_last_record") require.Error(t, err, "attestation request should fail with insufficient balance") require.Contains(t, err.Error(), "Insufficient balance for attestation", "error should mention insufficient balance") @@ -178,7 +178,7 @@ func testAttestationMultipleRequestsChargeFees(t *testing.T) func(ctx context.Co // Vary the time range for each request to get different attestation hashes from := int64(i * 1000) to := int64(i*1000 + 999) - err = requestAttestationWithTimeRange(ctx, platform, requesterAddr, systemAdmin.Address(), streamID, "get_record", from, to) + err = requestAttestationWithTimeRange(ctx, platform, requesterAddr, systemAdmin.Address(), streamID, "get_high_value", from, to) require.NoError(t, err, "attestation request %d should succeed", i+1) } @@ -225,7 +225,7 @@ func testAttestationLeaderReceivesFees(t *testing.T) func(ctx context.Context, p // Request attestation with specific leader systemAdmin := util.Unsafe_NewEthereumAddressFromString("0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf") streamID := "st000000000000000000000000000000" - err = requestAttestationWithLeader(ctx, platform, requesterAddr, pub, systemAdmin.Address(), streamID, "get_record") + err = requestAttestationWithLeader(ctx, platform, requesterAddr, pub, systemAdmin.Address(), streamID, "get_last_record") require.NoError(t, err, "attestation request with leader should succeed") // Verify leader balance increased by 40 TRUF @@ -254,15 +254,15 @@ func testAttestationBalanceCorrectlyDeducted(t *testing.T) func(ctx context.Cont streamID := "st000000000000000000000000000000" // First attestation should succeed (time range 0-999) - err = requestAttestationWithTimeRange(ctx, platform, requesterAddr, systemAdmin.Address(), streamID, "get_record", 0, 999) + err = requestAttestationWithTimeRange(ctx, platform, requesterAddr, systemAdmin.Address(), streamID, "get_high_value", 0, 999) require.NoError(t, err, "first attestation should succeed") // Second attestation should succeed (time range 1000-1999) - err = requestAttestationWithTimeRange(ctx, platform, requesterAddr, systemAdmin.Address(), streamID, "get_record", 1000, 1999) + err = requestAttestationWithTimeRange(ctx, platform, requesterAddr, systemAdmin.Address(), streamID, "get_high_value", 1000, 1999) require.NoError(t, err, "second attestation should succeed") // Third attestation should fail (insufficient balance) (time range 2000-2999) - err = requestAttestationWithTimeRange(ctx, platform, requesterAddr, systemAdmin.Address(), streamID, "get_record", 2000, 2999) + err = requestAttestationWithTimeRange(ctx, platform, requesterAddr, systemAdmin.Address(), streamID, "get_high_value", 2000, 2999) require.Error(t, err, "third attestation should fail with insufficient balance") require.Contains(t, err.Error(), "Insufficient balance for attestation", "error should mention insufficient balance") @@ -346,30 +346,46 @@ func getAttestationBalance(ctx context.Context, platform *kwilTesting.Platform, return balance, nil } -// callRequestAttestationAction is the base implementation - calls the request_attestation action +// callRequestAttestationAction calls request_attestation for single-point actions (get_last_record). +// Encodes args: ($data_provider, $stream_id, $before, $frozen_at, $use_cache) func callRequestAttestationAction(ctx context.Context, platform *kwilTesting.Platform, signer *util.EthereumAddress, leaderPub *crypto.Secp256k1PublicKey, dataProvider string, streamID string, actionName string) error { - return callRequestAttestationActionWithTimeRange(ctx, platform, signer, leaderPub, dataProvider, streamID, actionName, int64(0), int64(99999)) + actionArgs := []any{ + dataProvider, + streamID, + nil, // before + nil, // frozen_at + false, // use_cache + } + + argsBytes, err := tn_utils.EncodeActionArgs(actionArgs) + if err != nil { + return fmt.Errorf("failed to encode action args: %w", err) + } + + return callRequestAttestationWithBytes(ctx, platform, signer, leaderPub, dataProvider, streamID, actionName, argsBytes) } -// callRequestAttestationActionWithTimeRange is the base implementation with custom time range +// callRequestAttestationActionWithTimeRange calls request_attestation for range-based actions (get_high_value, get_low_value). +// Encodes args: ($data_provider, $stream_id, $from, $to, $frozen_at) func callRequestAttestationActionWithTimeRange(ctx context.Context, platform *kwilTesting.Platform, signer *util.EthereumAddress, leaderPub *crypto.Secp256k1PublicKey, dataProvider string, streamID string, actionName string, from int64, to int64) error { - // Prepare arguments for get_record action - // get_record($data_provider TEXT, $stream_id TEXT, $from INT8, $to INT8, $frozen_at INT8, $use_cache BOOL) actionArgs := []any{ dataProvider, streamID, from, to, - int64(99999), // frozen_at - false, // use_cache (will be forced to false by request_attestation) + nil, // frozen_at } - // Encode action arguments argsBytes, err := tn_utils.EncodeActionArgs(actionArgs) if err != nil { return fmt.Errorf("failed to encode action args: %w", err) } + return callRequestAttestationWithBytes(ctx, platform, signer, leaderPub, dataProvider, streamID, actionName, argsBytes) +} + +// callRequestAttestationWithBytes is the base implementation that calls request_attestation with pre-encoded args +func callRequestAttestationWithBytes(ctx context.Context, platform *kwilTesting.Platform, signer *util.EthereumAddress, leaderPub *crypto.Secp256k1PublicKey, dataProvider string, streamID string, actionName string, argsBytes []byte) error { tx := &common.TxContext{ Ctx: ctx, BlockContext: &common.BlockContext{ diff --git a/tests/streams/attestation/test_helpers.go b/tests/streams/attestation/test_helpers.go index ef25d76d7..04f55b6fa 100644 --- a/tests/streams/attestation/test_helpers.go +++ b/tests/streams/attestation/test_helpers.go @@ -24,7 +24,7 @@ import ( // Test data constants to avoid magic values const ( - TestActionIDRequest = 10 + TestActionIDRequest = 100 TestActionIDGet = 20 TestActionIDList = 21 TestStreamID = "stream_attestation_test_00000000" From 300d5de987b34c48c697eaec3b95a6376a615989 Mon Sep 17 00:00:00 2001 From: Michael Buntarman Date: Wed, 1 Apr 2026 03:30:10 +0700 Subject: [PATCH 2/2] chore: apply suggestion --- .../settlement_integration_test.go | 18 ++--- extensions/tn_utils/precompiles.go | 5 +- .../order_book/hash_compatibility_test.go | 11 ++- tests/streams/order_book/order_events_test.go | 6 +- tests/streams/order_book/settlement_test.go | 67 +++++++++---------- .../streams/transaction_events_ledger_test.go | 9 ++- 6 files changed, 59 insertions(+), 57 deletions(-) diff --git a/extensions/tn_settlement/settlement_integration_test.go b/extensions/tn_settlement/settlement_integration_test.go index 226648390..5eddf9bd4 100644 --- a/extensions/tn_settlement/settlement_integration_test.go +++ b/extensions/tn_settlement/settlement_integration_test.go @@ -603,15 +603,16 @@ func createStreamWithoutSigningAttestation( }, nil) require.NoError(t, err) - // Encode action args for get_record + // Encode action args for get_last_record + // Signature: ($data_provider, $stream_id, $before, $frozen_at, $use_cache) argsBytes, err := tn_utils.EncodeActionArgs([]any{ - dataProvider, streamID, int64(500), int64(1500), nil, false, + dataProvider, streamID, int64(1500), nil, false, }) require.NoError(t, err) // Request attestation (but don't sign) res, err := platform.Engine.Call(engineCtx, platform.DB, "", "request_attestation", - []any{dataProvider, streamID, "get_record", argsBytes, false, nil}, + []any{dataProvider, streamID, "get_last_record", argsBytes, false, nil}, func(row *common.Row) error { return nil }) @@ -623,7 +624,7 @@ func createStreamWithoutSigningAttestation( // NOTE: Intentionally NOT calling helper.SignAttestation() to test unsigned attestation // Return ABI-encoded query_components for create_market - queryComponents, err := encodeQueryComponents(dataProvider, streamID, "get_record", argsBytes) + queryComponents, err := encodeQueryComponents(dataProvider, streamID, "get_last_record", argsBytes) require.NoError(t, err) return queryComponents @@ -663,9 +664,10 @@ func createStreamAndAttestation( }, nil) require.NoError(t, err) - // Encode action args for get_record - MUST match what we use in request_attestation + // Encode action args for get_last_record - MUST match what we use in request_attestation + // Signature: ($data_provider, $stream_id, $before, $frozen_at, $use_cache) argsBytes, err := tn_utils.EncodeActionArgs([]any{ - dataProvider, streamID, int64(500), int64(1500), nil, false, + dataProvider, streamID, int64(1500), nil, false, }) require.NoError(t, err) @@ -673,7 +675,7 @@ func createStreamAndAttestation( var requestTxID string var attestationHash []byte res, err := platform.Engine.Call(engineCtx, platform.DB, "", "request_attestation", - []any{dataProvider, streamID, "get_record", argsBytes, false, nil}, + []any{dataProvider, streamID, "get_last_record", argsBytes, false, nil}, func(row *common.Row) error { requestTxID = row.Values[0].(string) attestationHash = append([]byte(nil), row.Values[1].([]byte)...) @@ -691,7 +693,7 @@ func createStreamAndAttestation( // Return ABI-encoded query_components for create_market // The hash is computed by create_market from these query_components - queryComponents, err := encodeQueryComponents(dataProvider, streamID, "get_record", argsBytes) + queryComponents, err := encodeQueryComponents(dataProvider, streamID, "get_last_record", argsBytes) require.NoError(t, err) return queryComponents diff --git a/extensions/tn_utils/precompiles.go b/extensions/tn_utils/precompiles.go index cb39af470..ca694e5b4 100644 --- a/extensions/tn_utils/precompiles.go +++ b/extensions/tn_utils/precompiles.go @@ -1161,11 +1161,14 @@ func getActionIDNumber(actionName string) (uint16, error) { "price_below_threshold": 7, "value_in_range": 8, "value_equals": 9, + // Single-row range actions (return TABLE(event_time INT8, value NUMERIC) LIMIT 1) + "get_high_value": 10, + "get_low_value": 11, } id, ok := actionMap[actionName] if !ok { - return 0, fmt.Errorf("unknown action: %s (valid actions: get_record, get_index, get_change_over_time, get_last_record, get_first_record, price_above_threshold, price_below_threshold, value_in_range, value_equals)", actionName) + return 0, fmt.Errorf("unknown action: %s", actionName) } return id, nil } diff --git a/tests/streams/order_book/hash_compatibility_test.go b/tests/streams/order_book/hash_compatibility_test.go index 9b43c111c..4239fecc1 100644 --- a/tests/streams/order_book/hash_compatibility_test.go +++ b/tests/streams/order_book/hash_compatibility_test.go @@ -119,20 +119,19 @@ func testHashCompatibility_MarketAndAttestation(t *testing.T) func(context.Conte // STEP 1: Create market with query_components // ====================================================================== - // Build query components for get_record action - // Args: data_provider, stream_id, from, to, frozen_at, use_cache + // Build query components for get_last_record action + // Args: data_provider, stream_id, before, frozen_at, use_cache argsBytes, err := tn_utils.EncodeActionArgs([]any{ dataProvider, streamID, - int64(500), // from - int64(1500), // to + int64(1500), // before nil, // frozen_at (NULL = latest) false, // use_cache }) require.NoError(t, err) // Encode query components using ABI - queryComponents, err := encodeQueryComponentsABIHashCompat(dataProvider, streamID, "get_record", argsBytes) + queryComponents, err := encodeQueryComponentsABIHashCompat(dataProvider, streamID, "get_last_record", argsBytes) require.NoError(t, err) // Create market @@ -177,7 +176,7 @@ func testHashCompatibility_MarketAndAttestation(t *testing.T) func(context.Conte []any{ dataProvider, streamID, - "get_record", + "get_last_record", argsBytes, false, // encrypt_sig nil, // max_fee diff --git a/tests/streams/order_book/order_events_test.go b/tests/streams/order_book/order_events_test.go index 46c33f6e4..95757f276 100644 --- a/tests/streams/order_book/order_events_test.go +++ b/tests/streams/order_book/order_events_test.go @@ -617,14 +617,14 @@ func testOrderEventSettlement(t *testing.T) func(ctx context.Context, platform * // Request and sign attestation argsBytes, err := tn_utils.EncodeActionArgs([]any{ - dataProvider, streamID, int64(500), int64(1500), nil, false, + dataProvider, streamID, int64(1500), nil, false, }) require.NoError(t, err) var requestTxID string engineCtx = helper.NewEngineContext() res, err := platform.Engine.Call(engineCtx, platform.DB, "", "request_attestation", - []any{dataProvider, streamID, "get_record", argsBytes, false, nil}, + []any{dataProvider, streamID, "get_last_record", argsBytes, false, nil}, func(row *common.Row) error { requestTxID = row.Values[0].(string) return nil @@ -635,7 +635,7 @@ func testOrderEventSettlement(t *testing.T) func(ctx context.Context, platform * helper.SignAttestation(requestTxID) // Create market - queryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_record", argsBytes) + queryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_last_record", argsBytes) require.NoError(t, err) settleTime := time.Now().Add(1 * time.Hour).Unix() diff --git a/tests/streams/order_book/settlement_test.go b/tests/streams/order_book/settlement_test.go index 6aec20ae4..0fe0d3b08 100644 --- a/tests/streams/order_book/settlement_test.go +++ b/tests/streams/order_book/settlement_test.go @@ -132,13 +132,12 @@ func testSettleMarketHappyPath(t *testing.T) func(context.Context, *kwilTesting. require.NoError(t, err) require.True(t, foundData, "Data should be found in stream") - // Request attestation for get_record - // Args: data_provider, stream_id, from, to, frozen_at, use_cache + // Request attestation for get_last_record + // Args: data_provider, stream_id, before, frozen_at, use_cache argsBytes, err := tn_utils.EncodeActionArgs([]any{ dataProvider, streamID, - int64(500), // from (before our eventTime=1000) - int64(1500), // to (after our eventTime=1000) + int64(1500), // before (after our eventTime=1000) nil, // frozen_at (NULL = latest) false, // use_cache }) @@ -150,7 +149,7 @@ func testSettleMarketHappyPath(t *testing.T) func(context.Context, *kwilTesting. []any{ dataProvider, streamID, - "get_record", + "get_last_record", argsBytes, false, // encrypt_sig nil, // max_fee @@ -173,7 +172,7 @@ func testSettleMarketHappyPath(t *testing.T) func(context.Context, *kwilTesting. // Encode query components for create_market (must match attestation args!) queryComponents, err := encodeQueryComponentsForTests( - dataProvider, streamID, "get_record", argsBytes) + dataProvider, streamID, "get_last_record", argsBytes) require.NoError(t, err) // Create market using query_components @@ -303,14 +302,14 @@ func testSettleMarketWithNoOutcome(t *testing.T) func(context.Context, *kwilTest // Request and sign attestation argsBytes, err := tn_utils.EncodeActionArgs([]any{ - dataProvider, streamID, int64(500), int64(1500), nil, false, + dataProvider, streamID, int64(1500), nil, false, }) require.NoError(t, err) var requestTxID string engineCtx = helper.NewEngineContext() _, err = platform.Engine.Call(engineCtx, platform.DB, "", "request_attestation", - []any{dataProvider, streamID, "get_record", argsBytes, false, nil}, + []any{dataProvider, streamID, "get_last_record", argsBytes, false, nil}, func(row *common.Row) error { requestTxID = row.Values[0].(string) // attestationHash not needed - using queryComponents @@ -320,7 +319,7 @@ func testSettleMarketWithNoOutcome(t *testing.T) func(context.Context, *kwilTest helper.SignAttestation(requestTxID) // Encode query components for create_market - queryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_record", argsBytes) + queryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_last_record", argsBytes) require.NoError(t, err) // Create and settle market @@ -414,14 +413,14 @@ func testSettleMarketWithMultipleDatapoints(t *testing.T) func(context.Context, // Request attestation for range containing all datapoints argsBytes, err := tn_utils.EncodeActionArgs([]any{ - dataProvider, streamID, int64(500), int64(3500), nil, false, + dataProvider, streamID, int64(3500), nil, false, }) require.NoError(t, err) var requestTxID string engineCtx = helper.NewEngineContext() _, err = platform.Engine.Call(engineCtx, platform.DB, "", "request_attestation", - []any{dataProvider, streamID, "get_record", argsBytes, false, nil}, + []any{dataProvider, streamID, "get_last_record", argsBytes, false, nil}, func(row *common.Row) error { requestTxID = row.Values[0].(string) // attestationHash not needed - using queryComponents @@ -431,7 +430,7 @@ func testSettleMarketWithMultipleDatapoints(t *testing.T) func(context.Context, helper.SignAttestation(requestTxID) // Encode query components for create_market - queryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_record", argsBytes) + queryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_last_record", argsBytes) require.NoError(t, err) // Create and settle market @@ -541,13 +540,13 @@ func testSettleMarketAlreadySettled(t *testing.T) func(context.Context, *kwilTes require.NoError(t, err) argsBytes, _ := tn_utils.EncodeActionArgs([]any{ - dataProvider, streamID, int64(500), int64(1500), nil, false, + dataProvider, streamID, int64(1500), nil, false, }) var requestTxID string engineCtx = helper.NewEngineContext() _, err = platform.Engine.Call(engineCtx, platform.DB, "", "request_attestation", - []any{dataProvider, streamID, "get_record", argsBytes, false, nil}, + []any{dataProvider, streamID, "get_last_record", argsBytes, false, nil}, func(row *common.Row) error { requestTxID = row.Values[0].(string) // attestationHash not needed - using queryComponents @@ -557,7 +556,7 @@ func testSettleMarketAlreadySettled(t *testing.T) func(context.Context, *kwilTes helper.SignAttestation(requestTxID) // Encode query components for create_market - queryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_record", argsBytes) + queryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_last_record", argsBytes) require.NoError(t, err) // Create market @@ -636,13 +635,13 @@ func testSettleMarketTooEarly(t *testing.T) func(context.Context, *kwilTesting.P require.NoError(t, err) argsBytes, _ := tn_utils.EncodeActionArgs([]any{ - dataProvider, streamID, int64(500), int64(1500), nil, false, + dataProvider, streamID, int64(1500), nil, false, }) var requestTxID string engineCtx = helper.NewEngineContext() _, err = platform.Engine.Call(engineCtx, platform.DB, "", "request_attestation", - []any{dataProvider, streamID, "get_record", argsBytes, false, nil}, + []any{dataProvider, streamID, "get_last_record", argsBytes, false, nil}, func(row *common.Row) error { requestTxID = row.Values[0].(string) // attestationHash not needed - using queryComponents @@ -652,7 +651,7 @@ func testSettleMarketTooEarly(t *testing.T) func(context.Context, *kwilTesting.P helper.SignAttestation(requestTxID) // Encode query components for create_market - queryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_record", argsBytes) + queryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_last_record", argsBytes) require.NoError(t, err) // Create market with settle_time = 1000 @@ -706,7 +705,7 @@ func testSettleMarketNoAttestation(t *testing.T) func(context.Context, *kwilTest // Create fake query components (no actual attestation exists) dataProvider := deployer.Address() streamID := "stfakeattest0000000000000000000" - fakeQueryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_record", nil) + fakeQueryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_last_record", nil) require.NoError(t, err) var queryID int @@ -776,12 +775,12 @@ func testSettleMarketAttestationNotSigned(t *testing.T) func(context.Context, *k require.NoError(t, err) argsBytes, _ := tn_utils.EncodeActionArgs([]any{ - dataProvider, streamID, int64(500), int64(1500), nil, false, + dataProvider, streamID, int64(1500), nil, false, }) engineCtx = helper.NewEngineContext() _, err = platform.Engine.Call(engineCtx, platform.DB, "", "request_attestation", - []any{dataProvider, streamID, "get_record", argsBytes, false, nil}, + []any{dataProvider, streamID, "get_last_record", argsBytes, false, nil}, func(row *common.Row) error { // attestation hash not needed - using queryComponents return nil @@ -790,7 +789,7 @@ func testSettleMarketAttestationNotSigned(t *testing.T) func(context.Context, *k // NOTE: Intentionally NOT signing the attestation // Encode query components for create_market - queryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_record", argsBytes) + queryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_last_record", argsBytes) require.NoError(t, err) // Create market @@ -876,14 +875,14 @@ func testSettleMarketValidationIntegration(t *testing.T) func(context.Context, * // Request and sign attestation argsBytes, err := tn_utils.EncodeActionArgs([]any{ - dataProvider, streamID, int64(500), int64(1500), nil, false, + dataProvider, streamID, int64(1500), nil, false, }) require.NoError(t, err) var requestTxID string engineCtx = helper.NewEngineContext() _, err = platform.Engine.Call(engineCtx, platform.DB, "", "request_attestation", - []any{dataProvider, streamID, "get_record", argsBytes, false, nil}, + []any{dataProvider, streamID, "get_last_record", argsBytes, false, nil}, func(row *common.Row) error { requestTxID = row.Values[0].(string) // attestationHash not needed - using queryComponents @@ -893,7 +892,7 @@ func testSettleMarketValidationIntegration(t *testing.T) func(context.Context, * helper.SignAttestation(requestTxID) // Encode query components for create_market - queryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_record", argsBytes) + queryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_last_record", argsBytes) require.NoError(t, err) // Create market @@ -985,13 +984,13 @@ func testSettleMarketBlockedByBinaryParityViolation(t *testing.T) func(context.C // Request and sign attestation argsBytes, _ := tn_utils.EncodeActionArgs([]any{ - dataProvider, streamID, int64(500), int64(1500), nil, false, + dataProvider, streamID, int64(1500), nil, false, }) var requestTxID string engineCtx = helper.NewEngineContext() _, err = platform.Engine.Call(engineCtx, platform.DB, "", "request_attestation", - []any{dataProvider, streamID, "get_record", argsBytes, false, nil}, + []any{dataProvider, streamID, "get_last_record", argsBytes, false, nil}, func(row *common.Row) error { requestTxID = row.Values[0].(string) // attestationHash not needed - using queryComponents @@ -1001,7 +1000,7 @@ func testSettleMarketBlockedByBinaryParityViolation(t *testing.T) func(context.C helper.SignAttestation(requestTxID) // Encode query components for create_market - queryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_record", argsBytes) + queryComponents, err := encodeQueryComponentsForTests(dataProvider, streamID, "get_last_record", argsBytes) require.NoError(t, err) // Create market @@ -1145,13 +1144,13 @@ func testSettleMarketMultiMarketCollateral(t *testing.T) func(context.Context, * require.NoError(t, err) argsBytes1, err := tn_utils.EncodeActionArgs([]any{ - dataProvider, streamID1, int64(500), int64(1500), nil, false, + dataProvider, streamID1, int64(1500), nil, false, }) require.NoError(t, err) var requestTxID1 string engineCtx = helper.NewEngineContext() res1, err := platform.Engine.Call(engineCtx, platform.DB, "", "request_attestation", - []any{dataProvider, streamID1, "get_record", argsBytes1, false, nil}, + []any{dataProvider, streamID1, "get_last_record", argsBytes1, false, nil}, func(row *common.Row) error { requestTxID1 = row.Values[0].(string) // attestation hash not needed - using queryComponents @@ -1166,7 +1165,7 @@ func testSettleMarketMultiMarketCollateral(t *testing.T) func(context.Context, * // Encode query components for market 1 queryComponents1, err := encodeQueryComponentsForTests( - dataProvider, streamID1, "get_record", argsBytes1) + dataProvider, streamID1, "get_last_record", argsBytes1) require.NoError(t, err) // ===== STREAM 2 ===== @@ -1187,13 +1186,13 @@ func testSettleMarketMultiMarketCollateral(t *testing.T) func(context.Context, * require.NoError(t, err) argsBytes2, err := tn_utils.EncodeActionArgs([]any{ - dataProvider, streamID2, int64(500), int64(1500), nil, false, + dataProvider, streamID2, int64(1500), nil, false, }) require.NoError(t, err) var requestTxID2 string engineCtx = helper.NewEngineContext() res2, err := platform.Engine.Call(engineCtx, platform.DB, "", "request_attestation", - []any{dataProvider, streamID2, "get_record", argsBytes2, false, nil}, + []any{dataProvider, streamID2, "get_last_record", argsBytes2, false, nil}, func(row *common.Row) error { requestTxID2 = row.Values[0].(string) // attestation hash not needed - using queryComponents @@ -1208,7 +1207,7 @@ func testSettleMarketMultiMarketCollateral(t *testing.T) func(context.Context, * // Encode query components for market 2 queryComponents2, err := encodeQueryComponentsForTests( - dataProvider, streamID2, "get_record", argsBytes2) + dataProvider, streamID2, "get_last_record", argsBytes2) require.NoError(t, err) // ===== CREATE MARKETS ===== diff --git a/tests/streams/transaction_events_ledger_test.go b/tests/streams/transaction_events_ledger_test.go index 6379fbd7b..6ec70f3b8 100644 --- a/tests/streams/transaction_events_ledger_test.go +++ b/tests/streams/transaction_events_ledger_test.go @@ -194,10 +194,9 @@ func runTransactionEventsLedgerScenario(t *testing.T) func(ctx context.Context, argsBytes, err := tn_utils.EncodeActionArgs([]any{ strings.ToLower(systemAdmin.Address()), attestationStream.String(), - int64(0), - int64(999), - int64(99999), - false, + int64(999), // before + int64(99999), // frozen_at + false, // use_cache }) require.NoError(t, err) @@ -205,7 +204,7 @@ func runTransactionEventsLedgerScenario(t *testing.T) func(ctx context.Context, attTx, err := callActionWithLeader(ctx, platform, actor, attLeaderPub, height, "request_attestation", []any{ strings.ToLower(systemAdmin.Address()), attestationStream.String(), - "get_record", + "get_last_record", argsBytes, false, nil,