-
Notifications
You must be signed in to change notification settings - Fork 404
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
"solo machine" client definition #309
Comments
Part of the idea behind the store layout abstraction was to avoid the requirement of fitting solo machines with single signing keys into the Did you consider that structure and reject it? If so, why? Although I admire your adaptation of the If you think the spec requires further updates to store abstraction in order to make that (simpler) flow possible, I am more than happy to make them. |
I'll defer to Joon for the specifics, but I think our stumbling block was the API between However, we had that discussion without looking very carefully at the code, so I imagine I'm wrong. When Joon comes by today, we'll walk through the spec and code and see if there's a simpler way. |
The client-specific verification function does include the port ID, channel ID, and sequence - check out I wonder if you might have been looking at an older version of the spec - or, if you were looking at the SDK-side code, do note that the SDK is currently implementing The delta between the spec & implementation is being tracked here and the particular issue tracking store layout abstraction implementation is here. (cc @fedekunze) |
See ICS 6 for the basic structure of how I think a solo machine client can work with the new store layout abstraction. Does that make sense? |
Bump - any thoughts from Agoric's side @warner? Would an implementation to play with help? I think @fedekunze will have it up pretty soon 🎉 . |
Yeah, I think we can have an SDK implementation by the end of next week |
@mossid has been helping us (Agoric) with the definition of a "solo machine" client type (related to #160). This would be for a standalone process that wants to speak IBC to a chain. Solo machines don't have provable public state like blockchains do, but they are capable of keeping secrets, like private signing keys. So the "client state" that a receiving chain is tracking is really just a public verifying key and a sequence number. And the "proof" that any given message was emitted by a chain is really a public-key signature.
The IBC specification allows for various "client types", so we're trying to define what the "solo machine client type" should contain. Here's what we have so far.
Suppose that Alice is a solo machine that wants to send messages to chains and/or other solo machines. Alice might have a single private signing key, or she might use separate keys for each correspondent. She maintains a separate "proof sequence number" for each of her correspondents, along with a unique static identifier (a chain-id). Her IBC subsystem will produce a variety of handshake messages, followed by a sequence of packets. We want the receiving chain to correctly accept the packets that Alice creates, in the right order, and reject any false messages injected by attackers.
Each packet will have a "packet sequence number". This grows by one for each packet she emits to a given recipient (they all share the same numberspace, so packet sequence number 4 on the Alice-Bob connection is unreltaed to 4 on the Alice-Carol connection). This packet sequence number does not include handshake messages. In contrast, the "proof sequence number" includes both packet messages and handshake messages.
When Alice creates a new packet, she builds a structure like this:
key
:ports/
$PORTID/channels/
$CHANNELID/packets/
$PacketSequenceNumbervalue
: packet dataproof
: emptyand she computes
MessageHash
as a hash of the safe concatenation ofkey
andvalue
. She then produces areceivePacket
message withkey
,value
,proof
(which is empty), and the current proof sequence number (asblockHeight
).Before sending this, she constructs a safe concatenation of her "chain-id" for the receipient, the proof sequence number, and the
MessageHash
. She applies her signing key to this body to produce theMessageSignature
.She then constructs a
Header
:height
: proof sequence numberhash
: theMessageHash
valuesig
: theMessageSignature
She builds an
updateClient
message around this Header (wherehash
is treated like the AppHash in a Tendermint block header, andsig
is like the set of validator signatures).Both the
updateClient
message and thereceivePacket
message are put into a Tendermint transaction and signed as usual. The key used to sign these messages is irrelevant (you'd want to deduct gas fees from the matching account, to prevent spam, but the transaction signing key is not meaningful to the IBC client verifier logic).On the chain, the
updateClient
message is processed first. The "solo client type" has a specificConsensusState
data structure that remembers:client-id
(aka chain-id) which this sender uses when talking to usEach client type has a table mapping (what it thinks of as) "block height" to (what it thinks of as) "app hash". For the solo client type, this maps proof sequence number to
MessageHash
.When the
updateClient
message arrives (with its Header), theupdateClient()
function does:height
matches the next expected proof sequence number, else rejectMessageHash
sig
against this body and the stored "next expected verifying key", else rejectheight
toMessageHash
to the tableLater, when the
receivePacket
message arrives, the IBC code will extractkey
,value
,proof
, andproofHeight
from the message. It will then call the client-type-specific verifier function with these four values. Our solo-client verifier function will:MessageHash
by hashing a safe concatenation ofkey
(which includes the packet sequence number) andvalue
(which has the actual packet data)proofHeight
to look up the expectedMessageHash
MessageHash
for equality, else rejectIf this works correctly, an attacker should not be able to spoof incoming messages, nor cause incoming messages to be rearranged. However, I'm concerned about the handshake messages, because e.g. all the
*Connection
messages use the samekey
string, and the message type (TryConnection
as opposed toAckConnection
) is not included in the hash (because the client-type verification function is not told which message contained the key/value pair being verified). So an attacker could take a message produced for one purpose and submit for a different purpose. As best we can tell, the two places that might be vulnerable to this are the four*Connection
messages (init, try, ack, confirm), and the four*Channel
messages (again named init, try, ack, and confirm). There are probably other defenses in place, but this is where my security-reviewer mindset told me to pay attention.The text was updated successfully, but these errors were encountered: