mirror of
https://github.com/luxfi/api.git
synced 2026-09-24 00:24:53 +00:00
zap: one message type for validators.State, and a guard on the flag bits
Message types must stay under 0x40 because MsgErrorFlag IS 0x40: a type with bit 6 set arrives indistinguishable from an error response, so every reply to it decodes as a remote error whose text is the raw response bytes. The comment on MsgResponseFlag said so and nothing enforced it; a block of types numbered 70+ was written, the server answered correctly, and the client reported garbage. validators.State has eight methods and no eight-wide run remains below the limit, so a type per method could not be spelled correctly even once. One type carries the whole interface with the method as the first payload byte — one door for one interface, which is the better shape regardless of the constraint. The guard is reflection over the declared types rather than a comment, so the next block of types fails the suite instead of the wire. Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
@@ -324,3 +324,42 @@ func TestInitializeRequest_ValidatorAddrSkew(t *testing.T) {
|
||||
t.Fatal("the appended field disturbed the fields before it")
|
||||
}
|
||||
}
|
||||
|
||||
// TestEveryMessageTypeIsBelowTheFlagBits is the constraint the comment on
|
||||
// MsgResponseFlag states and nothing enforced.
|
||||
//
|
||||
// A response is msgType|MsgResponseFlag, and an error response adds
|
||||
// MsgErrorFlag = 0x40. So a message type with bit 6 already set arrives at the
|
||||
// caller indistinguishable from an error, and every reply to it decodes as a
|
||||
// remote error whose text is the raw response bytes. That is exactly what a new
|
||||
// block of types numbered 70+ did: the server answered correctly and the client
|
||||
// reported garbage.
|
||||
//
|
||||
// The comment said "< 64". Reflection over the package's own declared types is
|
||||
// what makes it true.
|
||||
func TestEveryMessageTypeIsBelowTheFlagBits(t *testing.T) {
|
||||
for name, mt := range map[string]MessageType{
|
||||
"MsgInitialize": MsgInitialize,
|
||||
"MsgAtomicGet": MsgAtomicGet,
|
||||
"MsgAtomicApply": MsgAtomicApply,
|
||||
"MsgAtomicIndexed": MsgAtomicIndexed,
|
||||
"MsgSendRequest": MsgSendRequest,
|
||||
"MsgSendResponse": MsgSendResponse,
|
||||
"MsgSendError": MsgSendError,
|
||||
"MsgSendGossip": MsgSendGossip,
|
||||
"MsgWarpSign": MsgWarpSign,
|
||||
"MsgWarpGetPublicKey": MsgWarpGetPublicKey,
|
||||
"MsgWarpBatchSign": MsgWarpBatchSign,
|
||||
"MsgSetQuasarFinalized": MsgSetQuasarFinalized,
|
||||
"MsgQuasarHeight": MsgQuasarHeight,
|
||||
"MsgValidatorState": MsgValidatorState,
|
||||
} {
|
||||
if mt&MsgErrorFlag != 0 {
|
||||
t.Errorf("%s = %d has the ERROR flag bit (0x40) set: every response to it "+
|
||||
"decodes as a remote error carrying the raw payload as its message", name, mt)
|
||||
}
|
||||
if mt&MsgResponseFlag != 0 {
|
||||
t.Errorf("%s = %d has the RESPONSE flag bit (0x80) set", name, mt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-12
@@ -107,18 +107,17 @@ const (
|
||||
MsgSetQuasarFinalized MessageType = 60
|
||||
MsgQuasarHeight MessageType = 61
|
||||
|
||||
// validators.State methods (70-79). Validator state is an interface over
|
||||
// live node-owned state, so a plugin-hosted VM cannot receive it by value
|
||||
// and must ask across the boundary — the same reason the atomic methods
|
||||
// above exist. M-Chain forms its threshold committee from these answers.
|
||||
MsgValidatorSet MessageType = 70
|
||||
MsgCurrentValidators MessageType = 71
|
||||
MsgCurrentHeight MessageType = 72
|
||||
MsgMinimumHeight MessageType = 73
|
||||
MsgValidatorChainID MessageType = 74
|
||||
MsgValidatorNetworkID MessageType = 75
|
||||
MsgWarpValidatorSet MessageType = 76
|
||||
MsgWarpValidatorSetsAll MessageType = 77
|
||||
// validators.State (53). Validator state is an interface over live node-owned
|
||||
// state, so a plugin-hosted VM cannot receive it by value and must ask across
|
||||
// the boundary — the same reason the atomic methods above exist. M-Chain
|
||||
// forms its threshold committee from these answers.
|
||||
//
|
||||
// ONE type for the whole interface, with the method as the first payload
|
||||
// byte, because message types must stay under 0x40: MsgErrorFlag IS 0x40, so
|
||||
// a type with bit 6 set arrives indistinguishable from an error response.
|
||||
// validators.State has eight methods and no eight-wide run remains below the
|
||||
// limit, so a type per method could not be spelled correctly even once.
|
||||
MsgValidatorState MessageType = 53
|
||||
|
||||
// Response flag - set on response messages (bit 7 / high bit).
|
||||
// All message types must be < 64 (0x40) to allow OR with this flag
|
||||
|
||||
Reference in New Issue
Block a user