daitchain

x/state_channel Real (skeleton)

Nitro / ForceMove turn-taking over a Cosmos backend. Open with one tx, transact off-chain, close with one tx. 24-hour challenge window. Highest co-signed turn_num wins settlement.

Channel state machine

                  OpenChannel(escrow)         CooperativeClose
   (none) ----------------------------> OPEN -------------------> CLOSED
                                          |
                          ChallengeChannel|
                                          v
                                     CHALLENGED
                                     (24h window)
                          RespondChallenge|
                              (higher turn)
                                          v
                                     CHALLENGED -- EndBlocker --> SETTLED
                                                    (window
                                                     elapses)

The off-chain ChannelState carries a monotonic turn_num; whichever side presents the highest co-signed turn_num during the challenge window wins. MsgChallengeChannel opens the window; MsgRespondChallenge overwrites the on-chain best_state if state.turn_num > best_state.turn_num.

Genesis params

ParamDefaultNotes
channel_challenge_blocks86,487~24h at 999ms blocks
channel_max_duration86,487 * 30~30 days deadline ceiling
channel_max_participants9per design language

Messages

MsgOpenChannel        { user, host, model_id, max_calls, deadline,
                        escrow_amount }
MsgCloseChannel       { signer, channel_id, final_state }   // cooperative
MsgChallengeChannel   { signer, channel_id, last_signed_state }
MsgRespondChallenge   { signer, channel_id, higher_turn_state }
MsgUpdateParams       { authority, params }                 // gov-only

Queries

State layout

KeyPrefixChannel       channel_id -> Channel
KeyPrefixUserIndex     (user_addr, channel_id) -> ()
KeyPrefixHostIndex     (host_addr, channel_id) -> ()
KeyPrefixExpiryIndex   (expiry_height, channel_id) -> ()
KeyPrefixCounter       next_channel_id

Settlement payout math

On settle (cooperative or post-challenge):

spent_amount  = best_state.spent_amount
to_host       = spent_amount
refund_to_user = channel.escrow_amount - spent_amount
take_rate     = (settled separately by x/compute_market take rate if applicable)

What's wired today

Real KV layout, channel ID counter, all iterators, ValidateBasic for all 5 msgs and ChannelState.ValidateForChannel, the OPEN -> CHALLENGED -> SETTLED / CLOSED transitions, strict turn_num monotonicity check, settlement payout math, genesis init/export.

Phase 1 Bank movements, canonical ChannelState encoding + secp256k1 signature verification in VerifyChannelStateSig, pagination, typed events.

See also