-
Notifications
You must be signed in to change notification settings - Fork 0
SCP Gherkin Tests #10
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
base: main
Are you sure you want to change the base?
Changes from 3 commits
5e17c8f
6e1bf64
767f18c
16a55f4
6e030f5
c41fd02
fea6de7
f4c8d01
66243a3
6a1def7
ad3cb3e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| Feature: Sequencer | ||
| Once a StartInstance message is received, the sequencer filter its own transactions, sets a timer, | ||
| and begins simulating with a mailbox tracer. | ||
| It exchange messages with other sequencers and, | ||
| once the simulation produces a result, it votes and waits for a decision. | ||
|
|
||
| Background: | ||
| Given there is a chain "1" with sequencer "A" | ||
| Given there is a chain "2" with sequencer "B" | ||
|
|
||
| Scenario: Transaction filtering and timer | ||
| When sequencer "A" receives StartInstance with instance ID "0x1", period ID "1", sequence number "1", and xtrequest "1: [tx1_1,tx1_2], 2: [tx2]" | ||
| Then sequencer "A" should filter the transactions "[tx1_1,tx1_2]" | ||
| And sequencer "A" should start a timer for the instance "0x1" | ||
|
|
||
| Scenario: No transaction raises error | ||
| When sequencer "A" receives StartInstance with instance ID "0x1", period ID "1", sequence number "1", and xtrequest "2: [tx2], 3: [tx3]" | ||
| Then error "No transactions for this chain" should be returned | ||
|
|
||
| Scenario: Simulation raises error different from read miss | ||
| Given sequencer "A" receives StartInstance with instance ID "0x1", period ID "2", sequence number "2", and xtrequest "1: [tx1], 2: [tx2]" | ||
| When the execution engine simulates "tx1" and returns an error different than "Read miss" | ||
| Then sequencer "A" should send Vote to the shared publisher with instance ID "0x1", chain ID "1", and vote "false" | ||
|
|
||
| Scenario: Simulation successful | ||
| Given sequencer "A" receives StartInstance with instance ID "0x1", period ID "2", sequence number "2", and xtrequest "1: [tx1], 2: [tx2]" | ||
| When the execution engine simulates "tx1" and returns success | ||
| Then sequencer "A" should send Vote to the shared publisher with instance ID "0x1", chain ID "1", and vote "true" | ||
|
|
||
| Scenario: Read miss handled by storing expected message | ||
| Given sequencer "A" receives StartInstance with instance ID "0x1", period ID "2", sequence number "2", and xtrequest "1: [tx1], 2: [tx2]" | ||
| When the execution engine simulates "tx1" and returns a read miss for message with source chain ID "2", destination chain ID "1", source "0xabc", receiver "0xdef", session ID "0x123", label "MSG", and data "data" | ||
| Then sequencer "A" should store mailbox message with source chain ID "2", destination chain ID "1", source "0xabc", receiver "0xdef", session ID "0x123", label "MSG", and data "data" as expected message for instance ID "0x1" | ||
|
|
||
| Scenario: Written message is sent to the destination sequencer | ||
| Given sequencer "A" receives StartInstance with instance ID "0x1", period ID "3", sequence number "9", and xtrequest "1: [tx1], 2: [tx2]" | ||
| When the execution engine simulates "tx1" and emits a MailboxMessage with source chain "1", destination chain "2", source "0xaaa", receiver "0xbbb", session ID "0x777", label "TRANSFER", and data "[0x01,0x02]" | ||
| Then sequencer "A" should send MailboxMessage to sequencer "B" with instance ID "0x1", source chain "1", destination chain "2", source "0xaaa", receiver "0xbbb", session ID "0x777", label "TRANSFER", and data "[0x01,0x02]" | ||
|
|
||
| Scenario: A received mailbox message is stored as pending | ||
| Given sequencer "A" receives StartInstance with instance ID "0x1", period ID "3", sequence number "9", and xtrequest "1: [tx1], 2: [tx2]" | ||
| When sequencer "A" receives MailboxMessage with instance ID "0x1", source chain "2", destination chain "1", source "0x222", receiver "0x111", session ID "0x999", label "NOTE", and data "[0xab]" | ||
| Then sequencer "A" should append to the pending mailbox queue for instance ID "0x1" the message with source chain "2", destination chain "1", source "0x222", receiver "0x111", session ID "0x999", label "NOTE", and data "[0xab]" | ||
| And sequencer "A" should not trigger a new simulation | ||
|
|
||
| Scenario: A received mailbox message that is expected is added to the inbox and triggers a new simulation | ||
| Given sequencer "A" receives StartInstance with instance ID "0x1", period ID "2", sequence number "2", and xtrequest "1: [tx1], 2: [tx2]" | ||
| And the execution engine simulates "tx1" and returns a read miss for message with source chain ID "2", destination chain ID "1", source "0xabc", receiver "0xdef", session ID "0x123", label "MSG", and data "data" | ||
| And sequencer "A" should store mailbox message with source chain ID "2", destination chain ID "1", source "0xabc", receiver "0xdef", session ID "0x123", label "MSG", and data "data" as expected message for instance ID "0x1" | ||
| When sequencer "A" receives MailboxMessage with instance ID "0x1", source chain "2", destination chain "1", source "0xabc", receiver "0xdef", session ID "0x123", label "MSG", and data "data" | ||
| Then the sequencer should insert a mailbox.putInbox transaction above the transaction list for the message with source chain "2", destination chain "1", source "0xabc", receiver "0xdef", session ID "0x123", label "MSG", and data "data" | ||
| And sequencer "A" should start a new simulation | ||
|
|
||
| Scenario: Timeout before voting causes a rejection | ||
| Given sequencer "A" receives StartInstance with instance ID "0x1", period ID "2", sequence number "2", and xtrequest "1: [tx1], 2: [tx2]" | ||
| When the timer for instance ID "0x1" expires | ||
| Then sequencer "A" should send Vote to the shared publisher with instance ID "0x1", chain ID "1", and vote "false" | ||
| And sequencer "A" should mark the instance as rejected | ||
|
|
||
| Scenario Outline: Timeout after voting causes no action | ||
| Given sequencer "A" receives StartInstance with instance ID "0x1", period ID "2", sequence number "2", and xtrequest "1: [tx1], 2: [tx2]" | ||
| And sequencer "A" sent Vote to the shared publisher with instance ID "0x1", chain ID "1", and vote "<vote>" | ||
| When the timer for instance ID "0x1" expires | ||
| Then no additional Vote message should be sent | ||
|
|
||
| Examples: | ||
| | vote | | ||
| | true | | ||
| | false | | ||
|
|
||
| Scenario: Decision false causes rejection | ||
| Given sequencer "A" receives StartInstance with instance ID "0x1", period ID "2", sequence number "2", and xtrequest "1: [tx1], 2: [tx2]" | ||
| When sequencer "A" receives Decided from the shared publisher with instance ID "0x1" and decision "false" | ||
| Then sequencer "A" should mark the instance as rejected | ||
|
|
||
| Scenario: If decision true is received but no vote was sent, an error is raised | ||
| Given sequencer "A" receives StartInstance with instance ID "0x1", period ID "2", sequence number "2", and xtrequest "1: [tx1], 2: [tx2]" | ||
| And sequencer "A" has not sent Vote to the shared publisher with instance ID "0x1" | ||
| When sequencer "A" receives Decided from the shared publisher with instance ID "0x1" and decision "true" | ||
| Then error "decision true but no vote sent is an impossible state" should be returned | ||
|
|
||
| Scenario: Decision true causes finalization | ||
| Given sequencer "A" receives StartInstance with instance ID "0x1", period ID "2", sequence number "2", and xtrequest "1: [tx1], 2: [tx2]" | ||
| And the execution engine simulates "tx1" and returns success | ||
| And sequencer "A" sent Vote to the shared publisher with instance ID "0x1", chain ID "1", and vote "true" | ||
| When sequencer "A" receives Decided from the shared publisher with instance ID "0x1" and decision "true" | ||
| Then sequencer "A" should accept the instance | ||
|
|
||
| Scenario: Double decided is ignored and error is raised | ||
| Given sequencer "A" receives StartInstance with instance ID "0x1", period ID "2", sequence number "2", and xtrequest "1: [tx1], 2: [tx2]" | ||
| And sequencer "A" receives Decided from the shared publisher with instance ID "0x1" and decision "false" | ||
| When sequencer "A" receives Decided from the shared publisher with instance ID "0x1" and decision "true" | ||
| Then error "instance already decided" should be returned |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,247 @@ | ||
| Feature: Sequencer | ||
| Once the sequencer receives a StartInstance message it filters its own transactions, sets a timer, | ||
| and begins simulating with a mailbox tracer. It exchanges messages with peer sequencers and, | ||
| after the simulation completes, it votes and waits for a decision. | ||
|
|
||
| Background: | ||
| Given there is a chain "1" with sequencer "A" | ||
| And there is a chain "2" with sequencer "B" | ||
|
|
||
| @start-instance | ||
|
||
| Scenario: Filters local transactions and starts a timer | ||
| When sequencer "A" receives StartInstance: | ||
| """ | ||
| instance_id: 0x1 | ||
| period_id: 1 | ||
| sequence_number: 1 | ||
| xtrequest: | ||
| 1: [tx1_1, tx1_2] | ||
| 2: [tx2] | ||
| """ | ||
| Then sequencer "A" should only consider transactions "[tx1_1,tx1_2]" for simulation | ||
| And a timer for instance "0x1" should start | ||
|
|
||
| @start-instance | ||
| Scenario: Rejects StartInstance with no local transactions | ||
| When sequencer "A" receives StartInstance: | ||
| """ | ||
| instance_id: 0x1 | ||
| period_id: 1 | ||
| sequence_number: 1 | ||
| xtrequest: | ||
| 2: [tx2] | ||
| 3: [tx3] | ||
| """ | ||
| Then an error occurs: | ||
| """ | ||
| No transactions for this chain | ||
| """ | ||
|
|
||
| @simulation | ||
| Scenario Outline: Votes according to simulation outcome | ||
| Given sequencer "A" receives StartInstance: | ||
| """ | ||
| instance_id: 0x1 | ||
| period_id: 2 | ||
| sequence_number: 2 | ||
| xtrequest: | ||
| 1: [tx1] | ||
| 2: [tx2] | ||
| """ | ||
| When the execution engine simulates "tx1" and <result> | ||
| Then sequencer "A" should publish Vote with: | ||
| | field | value | | ||
| | instance_id | 0x1 | | ||
| | chain_id | 1 | | ||
| | vote | <vote> | | ||
|
|
||
| Examples: | ||
| | result | vote | | ||
| | returns success | true | | ||
| | returns an error other than "Read miss" | false | | ||
|
||
|
|
||
| @mailbox @simulation | ||
|
||
| Scenario: Records expected mailbox message after read miss | ||
| Given sequencer "A" receives StartInstance: | ||
| """ | ||
| instance_id: 0x1 | ||
| period_id: 2 | ||
| sequence_number: 2 | ||
| xtrequest: | ||
| 1: [tx1] | ||
| 2: [tx2] | ||
| """ | ||
| When the execution engine simulates "tx1" and returns a read miss for mailbox message: | ||
| | field | value | | ||
| | source_chain_id | 2 | | ||
| | destination_chain_id | 1 | | ||
| | source | 0xabc | | ||
| | receiver | 0xdef | | ||
| | session_id | 0x123 | | ||
| | label | MSG | | ||
| | data | data | | ||
| Then sequencer "A" should record that mailbox message as expected for instance "0x1" | ||
|
|
||
| @mailbox | ||
| Scenario: Sends written mailbox message to the destination sequencer | ||
| Given sequencer "A" receives StartInstance: | ||
| """ | ||
| instance_id: 0x1 | ||
| period_id: 3 | ||
| sequence_number: 9 | ||
| xtrequest: | ||
| 1: [tx1] | ||
| 2: [tx2] | ||
| """ | ||
| When the execution engine simulates "tx1" and emits MailboxMessage: | ||
| | field | value | | ||
| | source_chain | 1 | | ||
| | destination_chain | 2 | | ||
| | source | 0xaaa | | ||
| | receiver | 0xbbb | | ||
| | session_id | 0x777 | | ||
| | label | TRANSFER | | ||
| | data | [0x01,0x02] | | ||
| Then sequencer "A" should forward that MailboxMessage to sequencer "B" with instance ID "0x1" | ||
|
|
||
| @mailbox | ||
| Scenario Outline: Handles inbound mailbox messages based on expectation | ||
| Given sequencer "A" receives StartInstance: | ||
| """ | ||
| instance_id: 0x1 | ||
| period_id: 2 | ||
| sequence_number: 2 | ||
| xtrequest: | ||
| 1: [tx1] | ||
| 2: [tx2] | ||
| """ | ||
| And sequencer "A" <expected_state> an expected mailbox message with: | ||
| | field | value | | ||
| | source_chain | 2 | | ||
| | destination_chain | 1 | | ||
| | source | 0xabc | | ||
| | receiver | 0xdef | | ||
| | session_id | 0x123 | | ||
| | label | MSG | | ||
| | data | data | | ||
| When sequencer "A" receives MailboxMessage with the same payload and instance ID "0x1" | ||
| Then <storage_result> | ||
| And <simulation_effect> | ||
|
|
||
| Examples: | ||
| | expected_state | storage_result | simulation_effect | | ||
| | has not stored | the message is appended to the pending mailbox queue for instance "0x1" | sequencer "A" should not start a new simulation | | ||
| | has already stored | the message is moved to the inbox and a mailbox.putInbox transaction is inserted before others | sequencer "A" should start a new simulation | | ||
|
|
||
| @timeout | ||
| Scenario: Rejects instance when timer expires before voting | ||
| Given sequencer "A" receives StartInstance: | ||
| """ | ||
| instance_id: 0x1 | ||
| period_id: 2 | ||
| sequence_number: 2 | ||
| xtrequest: | ||
| 1: [tx1] | ||
| 2: [tx2] | ||
| """ | ||
| When the timer for instance ID "0x1" expires | ||
| Then sequencer "A" should publish Vote with: | ||
| | field | value | | ||
| | instance_id | 0x1 | | ||
| | chain_id | 1 | | ||
| | vote | false | | ||
| And sequencer "A" should mark the instance "0x1" as rejected | ||
|
|
||
| @timeout | ||
| Scenario Outline: Ignores timer expiry after voting | ||
| Given sequencer "A" receives StartInstance: | ||
| """ | ||
| instance_id: 0x1 | ||
| period_id: 2 | ||
| sequence_number: 2 | ||
| xtrequest: | ||
| 1: [tx1] | ||
| 2: [tx2] | ||
| """ | ||
| And sequencer "A" previously published Vote with: | ||
| | field | value | | ||
| | instance_id | 0x1 | | ||
| | chain_id | 1 | | ||
| | vote | <vote> | | ||
| When the timer for instance ID "0x1" expires | ||
| Then no additional Vote message should be sent | ||
|
|
||
| Examples: | ||
| | vote | | ||
| | true | | ||
| | false | | ||
|
|
||
| @decision | ||
| Scenario: Rejects instance when decision is false | ||
| Given sequencer "A" receives StartInstance: | ||
| """ | ||
| instance_id: 0x1 | ||
| period_id: 2 | ||
| sequence_number: 2 | ||
| xtrequest: | ||
| 1: [tx1] | ||
| 2: [tx2] | ||
| """ | ||
| When sequencer "A" receives Decided for instance "0x1" with decision "false" | ||
| Then sequencer "A" should mark the instance "0x1" as rejected | ||
|
|
||
| @decision | ||
| Scenario: Errors when decision true arrives without a prior vote | ||
| Given sequencer "A" receives StartInstance: | ||
| """ | ||
| instance_id: 0x1 | ||
| period_id: 2 | ||
| sequence_number: 2 | ||
| xtrequest: | ||
| 1: [tx1] | ||
| 2: [tx2] | ||
| """ | ||
| And sequencer "A" has not published a Vote for instance "0x1" | ||
| When sequencer "A" receives Decided for instance "0x1" with decision "true" | ||
| Then an error occurs: | ||
| """ | ||
| decision true but no vote sent is an impossible state | ||
| """ | ||
|
|
||
| @decision | ||
| Scenario: Finalizes instance when decision true matches prior vote | ||
| Given sequencer "A" receives StartInstance: | ||
| """ | ||
| instance_id: 0x1 | ||
| period_id: 2 | ||
| sequence_number: 2 | ||
| xtrequest: | ||
| 1: [tx1] | ||
| 2: [tx2] | ||
| """ | ||
| And the execution engine simulates "tx1" and returns success | ||
| And sequencer "A" previously published Vote with: | ||
| | field | value | | ||
| | instance_id | 0x1 | | ||
| | chain_id | 1 | | ||
| | vote | true | | ||
| When sequencer "A" receives Decided for instance "0x1" with decision "true" | ||
| Then sequencer "A" should accept the instance "0x1" | ||
|
|
||
| @decision | ||
| Scenario: Raises error when a decided instance receives a second decision | ||
| Given sequencer "A" receives StartInstance: | ||
| """ | ||
| instance_id: 0x1 | ||
| period_id: 2 | ||
| sequence_number: 2 | ||
| xtrequest: | ||
| 1: [tx1] | ||
| 2: [tx2] | ||
| """ | ||
| And sequencer "A" receives Decided for instance "0x1" with decision "false" | ||
| When sequencer "A" later receives Decided for instance "0x1" with decision "true" | ||
| Then an error occurs: | ||
| """ | ||
| instance already decided | ||
| """ | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note it is also possible to put tags here