function verifyMembership(
clientState: ClientState,
// provided height is unnecessary for solomachine
// since clientState maintains the expected sequence
height: uint64,
// delayPeriod is unsupported on solomachines
// thus these fields are ignored
delayTimePeriod: uint64,
delayBlockPeriod: uint64,
proof: CommitmentProof,
path: CommitmentPath,
value: []byte
): Error {
// the expected sequence used in the signature
abortTransactionUnless(!clientState.frozen)
abortTransactionUnless(proof.timestamp >= clientState.consensusState.timestamp)
// path is prefixed with the store prefix of the commitment proof
// e.g. in ibc-go implementation this is "ibc"
// since solomachines do not use multi-stores, the prefix needs
// to be removed from the path to retrieve the correct key in the
// solomachine store
unprefixedPath = removePrefix(getCommitmentPrefix(), path)
signBytes = SignBytes(
sequence: clientState.sequence,
timestamp: proof.timestamp,
diversifier: clientState.consensusState.diversifier,
path: unprefixedPath,
data: value,
)
proven = checkSignature(clientState.consensusState.publicKey, signBytes, proof.sig)
if !proven {
return error
}
// increment sequence on each verification to provide
// replay protection
clientState.sequence++
clientState.consensusState.timestamp = proof.timestamp
// unlike other clients, we must set the client state here because we
// mutate the clientState (increment sequence and set timestamp)
// thus the verification methods are stateful for the solomachine
// in order to prevent replay attacks
provableStore.set("clients/{identifier}/clientState", clientState)
return nil
}
function verifyNonMembership(
clientState: ClientState,
// provided height is unnecessary for solomachine
// since clientState maintains the expected sequence
height: uint64,
// delayPeriod is unsupported on solomachines
// thus these fields are ignored
delayTimePeriod: uint64,
delayBlockPeriod: uint64,
proof: CommitmentProof,
path: CommitmentPath
): Error {
abortTransactionUnless(!clientState.frozen)
abortTransactionUnless(proof.timestamp >= clientState.consensusState.timestamp)
// path is prefixed with the store prefix of the commitment proof
// e.g. in ibc-go implementation this is "ibc"
// since solomachines do not use multi-stores, the prefix needs
// to be removed from the path to retrieve the correct key in the
// solomachine store
unprefixedPath = removePrefix(getCommitmentPrefix(), path)
signBytes = SignBytes(
sequence: clientState.sequence,
timestamp: proof.timestamp,
diversifier: clientState.consensusState.diversifier,
path: unprefixedPath,
data: nil,
)
proven = checkSignature(clientState.consensusState.publicKey, signBytes, proof.sig)
if !proven {
return error
}
// increment sequence on each verification to provide
// replay protection
clientState.sequence++
clientState.consensusState.timestamp = proof.timestamp
// unlike other clients, we must set the client state here because we
// mutate the clientState (increment sequence and set timestamp)
// thus the verification methods are stateful for the solomachine
// in order to prevent replay attacks
provableStore.set("clients/{identifier}/clientState", clientState)
return nil
}