fix: clean up rust ffi, background coverage events, and sync tweaks

This commit is contained in:
Cassandra Heart 2026-01-03 23:49:01 -06:00
parent 9f6174e39b
commit 0098ebe93c
No known key found for this signature in database
GPG Key ID: 371083BFA6C240AA
12 changed files with 554 additions and 380 deletions

View File

@ -163,44 +163,87 @@ func NewTripleRatchet(
func DoubleRatchetEncrypt(
ratchetStateAndMessage generated.DoubleRatchetStateAndMessage,
) generated.DoubleRatchetStateAndEnvelope {
return generated.DoubleRatchetEncrypt(ratchetStateAndMessage)
result, err := generated.DoubleRatchetEncrypt(ratchetStateAndMessage)
if err != nil {
return generated.DoubleRatchetStateAndEnvelope{}
}
return result
}
func DoubleRatchetDecrypt(
ratchetStateAndEnvelope generated.DoubleRatchetStateAndEnvelope,
) generated.DoubleRatchetStateAndMessage {
return generated.DoubleRatchetDecrypt(ratchetStateAndEnvelope)
result, err := generated.DoubleRatchetDecrypt(ratchetStateAndEnvelope)
if err != nil {
return generated.DoubleRatchetStateAndMessage{}
}
return result
}
func TripleRatchetInitRound1(
ratchetStateAndMetadata generated.TripleRatchetStateAndMetadata,
) generated.TripleRatchetStateAndMetadata {
return generated.TripleRatchetInitRound1(ratchetStateAndMetadata)
result, err := generated.TripleRatchetInitRound1(ratchetStateAndMetadata)
if err != nil {
return generated.TripleRatchetStateAndMetadata{
Metadata: map[string]string{"error": err.Error()},
}
}
return result
}
func TripleRatchetInitRound2(
ratchetStateAndMetadata generated.TripleRatchetStateAndMetadata,
) generated.TripleRatchetStateAndMetadata {
return generated.TripleRatchetInitRound2(ratchetStateAndMetadata)
result, err := generated.TripleRatchetInitRound2(ratchetStateAndMetadata)
if err != nil {
return generated.TripleRatchetStateAndMetadata{
Metadata: map[string]string{"error": err.Error()},
}
}
return result
}
func TripleRatchetInitRound3(
ratchetStateAndMetadata generated.TripleRatchetStateAndMetadata,
) generated.TripleRatchetStateAndMetadata {
return generated.TripleRatchetInitRound3(ratchetStateAndMetadata)
result, err := generated.TripleRatchetInitRound3(ratchetStateAndMetadata)
if err != nil {
return generated.TripleRatchetStateAndMetadata{
Metadata: map[string]string{"error": err.Error()},
}
}
return result
}
func TripleRatchetInitRound4(
ratchetStateAndMetadata generated.TripleRatchetStateAndMetadata,
) generated.TripleRatchetStateAndMetadata {
return generated.TripleRatchetInitRound4(ratchetStateAndMetadata)
result, err := generated.TripleRatchetInitRound4(ratchetStateAndMetadata)
if err != nil {
return generated.TripleRatchetStateAndMetadata{
Metadata: map[string]string{"error": err.Error()},
}
}
return result
}
func TripleRatchetEncrypt(
ratchetStateAndMessage generated.TripleRatchetStateAndMessage,
) generated.TripleRatchetStateAndEnvelope {
return generated.TripleRatchetEncrypt(ratchetStateAndMessage)
result, err := generated.TripleRatchetEncrypt(ratchetStateAndMessage)
if err != nil {
return generated.TripleRatchetStateAndEnvelope{}
}
return result
}
func TripleRatchetDecrypt(
ratchetStateAndEnvelope generated.TripleRatchetStateAndEnvelope,
) generated.TripleRatchetStateAndMessage {
return generated.TripleRatchetDecrypt(ratchetStateAndEnvelope)
result, err := generated.TripleRatchetDecrypt(ratchetStateAndEnvelope)
if err != nil {
return generated.TripleRatchetStateAndMessage{}
}
return result
}

View File

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["lib", "staticlib"]
crate-type = ["lib", "staticlib", "cdylib"]
name = "channel"
[[bin]]

View File

@ -748,6 +748,8 @@ internal interface UniffiForeignFutureCompleteVoid : com.sun.jna.Callback {
@ -804,6 +806,8 @@ internal interface UniffiLib : Library {
): RustBuffer.ByValue
fun uniffi_channel_fn_func_triple_ratchet_init_round_4(`ratchetStateAndMetadata`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus,
): RustBuffer.ByValue
fun uniffi_channel_fn_func_triple_ratchet_resize(`ratchetState`: RustBuffer.ByValue,`other`: RustBuffer.ByValue,`id`: Long,`total`: Long,uniffi_out_err: UniffiRustCallStatus,
): RustBuffer.ByValue
fun uniffi_channel_fn_func_verify_ed448(`publicKey`: RustBuffer.ByValue,`message`: RustBuffer.ByValue,`signature`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus,
): RustBuffer.ByValue
fun ffi_channel_rustbuffer_alloc(`size`: Long,uniffi_out_err: UniffiRustCallStatus,
@ -956,6 +960,8 @@ internal interface UniffiLib : Library {
): Short
fun uniffi_channel_checksum_func_triple_ratchet_init_round_4(
): Short
fun uniffi_channel_checksum_func_triple_ratchet_resize(
): Short
fun uniffi_channel_checksum_func_verify_ed448(
): Short
fun ffi_channel_uniffi_contract_version(
@ -978,10 +984,10 @@ private fun uniffiCheckApiChecksums(lib: UniffiLib) {
if (lib.uniffi_channel_checksum_func_decrypt_inbox_message() != 59344.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_channel_checksum_func_double_ratchet_decrypt() != 13335.toShort()) {
if (lib.uniffi_channel_checksum_func_double_ratchet_decrypt() != 59687.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_channel_checksum_func_double_ratchet_encrypt() != 59209.toShort()) {
if (lib.uniffi_channel_checksum_func_double_ratchet_encrypt() != 57909.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_channel_checksum_func_encrypt_inbox_message() != 48273.toShort()) {
@ -1014,22 +1020,25 @@ private fun uniffiCheckApiChecksums(lib: UniffiLib) {
if (lib.uniffi_channel_checksum_func_sign_ed448() != 28573.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_channel_checksum_func_triple_ratchet_decrypt() != 42324.toShort()) {
if (lib.uniffi_channel_checksum_func_triple_ratchet_decrypt() != 15842.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_channel_checksum_func_triple_ratchet_encrypt() != 61617.toShort()) {
if (lib.uniffi_channel_checksum_func_triple_ratchet_encrypt() != 23451.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_channel_checksum_func_triple_ratchet_init_round_1() != 42612.toShort()) {
if (lib.uniffi_channel_checksum_func_triple_ratchet_init_round_1() != 63112.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_channel_checksum_func_triple_ratchet_init_round_2() != 11875.toShort()) {
if (lib.uniffi_channel_checksum_func_triple_ratchet_init_round_2() != 34197.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_channel_checksum_func_triple_ratchet_init_round_3() != 50331.toShort()) {
if (lib.uniffi_channel_checksum_func_triple_ratchet_init_round_3() != 39476.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_channel_checksum_func_triple_ratchet_init_round_4() != 14779.toShort()) {
if (lib.uniffi_channel_checksum_func_triple_ratchet_init_round_4() != 19263.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_channel_checksum_func_triple_ratchet_resize() != 57124.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_channel_checksum_func_verify_ed448() != 57200.toShort()) {
@ -1371,6 +1380,83 @@ public object FfiConverterTypeTripleRatchetStateAndMetadata: FfiConverterRustBuf
sealed class CryptoException(message: String): kotlin.Exception(message) {
class InvalidState(message: String) : CryptoException(message)
class InvalidEnvelope(message: String) : CryptoException(message)
class DecryptionFailed(message: String) : CryptoException(message)
class EncryptionFailed(message: String) : CryptoException(message)
class SerializationFailed(message: String) : CryptoException(message)
class InvalidInput(message: String) : CryptoException(message)
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<CryptoException> {
override fun lift(error_buf: RustBuffer.ByValue): CryptoException = FfiConverterTypeCryptoError.lift(error_buf)
}
}
/**
* @suppress
*/
public object FfiConverterTypeCryptoError : FfiConverterRustBuffer<CryptoException> {
override fun read(buf: ByteBuffer): CryptoException {
return when(buf.getInt()) {
1 -> CryptoException.InvalidState(FfiConverterString.read(buf))
2 -> CryptoException.InvalidEnvelope(FfiConverterString.read(buf))
3 -> CryptoException.DecryptionFailed(FfiConverterString.read(buf))
4 -> CryptoException.EncryptionFailed(FfiConverterString.read(buf))
5 -> CryptoException.SerializationFailed(FfiConverterString.read(buf))
6 -> CryptoException.InvalidInput(FfiConverterString.read(buf))
else -> throw RuntimeException("invalid error enum value, something is very wrong!!")
}
}
override fun allocationSize(value: CryptoException): ULong {
return 4UL
}
override fun write(value: CryptoException, buf: ByteBuffer) {
when(value) {
is CryptoException.InvalidState -> {
buf.putInt(1)
Unit
}
is CryptoException.InvalidEnvelope -> {
buf.putInt(2)
Unit
}
is CryptoException.DecryptionFailed -> {
buf.putInt(3)
Unit
}
is CryptoException.EncryptionFailed -> {
buf.putInt(4)
Unit
}
is CryptoException.SerializationFailed -> {
buf.putInt(5)
Unit
}
is CryptoException.InvalidInput -> {
buf.putInt(6)
Unit
}
}.let { /* this makes the `when` an expression, which ensures it is exhaustive */ }
}
}
/**
* @suppress
*/
@ -1470,18 +1556,20 @@ public object FfiConverterMapStringString: FfiConverterRustBuffer<Map<kotlin.Str
)
}
fun `doubleRatchetDecrypt`(`ratchetStateAndEnvelope`: DoubleRatchetStateAndEnvelope): DoubleRatchetStateAndMessage {
@Throws(CryptoException::class) fun `doubleRatchetDecrypt`(`ratchetStateAndEnvelope`: DoubleRatchetStateAndEnvelope): DoubleRatchetStateAndMessage {
return FfiConverterTypeDoubleRatchetStateAndMessage.lift(
uniffiRustCall() { _status ->
uniffiRustCallWithError(CryptoException) { _status ->
UniffiLib.INSTANCE.uniffi_channel_fn_func_double_ratchet_decrypt(
FfiConverterTypeDoubleRatchetStateAndEnvelope.lower(`ratchetStateAndEnvelope`),_status)
}
)
}
fun `doubleRatchetEncrypt`(`ratchetStateAndMessage`: DoubleRatchetStateAndMessage): DoubleRatchetStateAndEnvelope {
@Throws(CryptoException::class) fun `doubleRatchetEncrypt`(`ratchetStateAndMessage`: DoubleRatchetStateAndMessage): DoubleRatchetStateAndEnvelope {
return FfiConverterTypeDoubleRatchetStateAndEnvelope.lift(
uniffiRustCall() { _status ->
uniffiRustCallWithError(CryptoException) { _status ->
UniffiLib.INSTANCE.uniffi_channel_fn_func_double_ratchet_encrypt(
FfiConverterTypeDoubleRatchetStateAndMessage.lower(`ratchetStateAndMessage`),_status)
}
@ -1578,60 +1666,75 @@ public object FfiConverterMapStringString: FfiConverterRustBuffer<Map<kotlin.Str
)
}
fun `tripleRatchetDecrypt`(`ratchetStateAndEnvelope`: TripleRatchetStateAndEnvelope): TripleRatchetStateAndMessage {
@Throws(CryptoException::class) fun `tripleRatchetDecrypt`(`ratchetStateAndEnvelope`: TripleRatchetStateAndEnvelope): TripleRatchetStateAndMessage {
return FfiConverterTypeTripleRatchetStateAndMessage.lift(
uniffiRustCall() { _status ->
uniffiRustCallWithError(CryptoException) { _status ->
UniffiLib.INSTANCE.uniffi_channel_fn_func_triple_ratchet_decrypt(
FfiConverterTypeTripleRatchetStateAndEnvelope.lower(`ratchetStateAndEnvelope`),_status)
}
)
}
fun `tripleRatchetEncrypt`(`ratchetStateAndMessage`: TripleRatchetStateAndMessage): TripleRatchetStateAndEnvelope {
@Throws(CryptoException::class) fun `tripleRatchetEncrypt`(`ratchetStateAndMessage`: TripleRatchetStateAndMessage): TripleRatchetStateAndEnvelope {
return FfiConverterTypeTripleRatchetStateAndEnvelope.lift(
uniffiRustCall() { _status ->
uniffiRustCallWithError(CryptoException) { _status ->
UniffiLib.INSTANCE.uniffi_channel_fn_func_triple_ratchet_encrypt(
FfiConverterTypeTripleRatchetStateAndMessage.lower(`ratchetStateAndMessage`),_status)
}
)
}
fun `tripleRatchetInitRound1`(`ratchetStateAndMetadata`: TripleRatchetStateAndMetadata): TripleRatchetStateAndMetadata {
@Throws(CryptoException::class) fun `tripleRatchetInitRound1`(`ratchetStateAndMetadata`: TripleRatchetStateAndMetadata): TripleRatchetStateAndMetadata {
return FfiConverterTypeTripleRatchetStateAndMetadata.lift(
uniffiRustCall() { _status ->
uniffiRustCallWithError(CryptoException) { _status ->
UniffiLib.INSTANCE.uniffi_channel_fn_func_triple_ratchet_init_round_1(
FfiConverterTypeTripleRatchetStateAndMetadata.lower(`ratchetStateAndMetadata`),_status)
}
)
}
fun `tripleRatchetInitRound2`(`ratchetStateAndMetadata`: TripleRatchetStateAndMetadata): TripleRatchetStateAndMetadata {
@Throws(CryptoException::class) fun `tripleRatchetInitRound2`(`ratchetStateAndMetadata`: TripleRatchetStateAndMetadata): TripleRatchetStateAndMetadata {
return FfiConverterTypeTripleRatchetStateAndMetadata.lift(
uniffiRustCall() { _status ->
uniffiRustCallWithError(CryptoException) { _status ->
UniffiLib.INSTANCE.uniffi_channel_fn_func_triple_ratchet_init_round_2(
FfiConverterTypeTripleRatchetStateAndMetadata.lower(`ratchetStateAndMetadata`),_status)
}
)
}
fun `tripleRatchetInitRound3`(`ratchetStateAndMetadata`: TripleRatchetStateAndMetadata): TripleRatchetStateAndMetadata {
@Throws(CryptoException::class) fun `tripleRatchetInitRound3`(`ratchetStateAndMetadata`: TripleRatchetStateAndMetadata): TripleRatchetStateAndMetadata {
return FfiConverterTypeTripleRatchetStateAndMetadata.lift(
uniffiRustCall() { _status ->
uniffiRustCallWithError(CryptoException) { _status ->
UniffiLib.INSTANCE.uniffi_channel_fn_func_triple_ratchet_init_round_3(
FfiConverterTypeTripleRatchetStateAndMetadata.lower(`ratchetStateAndMetadata`),_status)
}
)
}
fun `tripleRatchetInitRound4`(`ratchetStateAndMetadata`: TripleRatchetStateAndMetadata): TripleRatchetStateAndMetadata {
@Throws(CryptoException::class) fun `tripleRatchetInitRound4`(`ratchetStateAndMetadata`: TripleRatchetStateAndMetadata): TripleRatchetStateAndMetadata {
return FfiConverterTypeTripleRatchetStateAndMetadata.lift(
uniffiRustCall() { _status ->
uniffiRustCallWithError(CryptoException) { _status ->
UniffiLib.INSTANCE.uniffi_channel_fn_func_triple_ratchet_init_round_4(
FfiConverterTypeTripleRatchetStateAndMetadata.lower(`ratchetStateAndMetadata`),_status)
}
)
}
fun `tripleRatchetResize`(`ratchetState`: kotlin.String, `other`: kotlin.String, `id`: kotlin.ULong, `total`: kotlin.ULong): List<List<kotlin.UByte>> {
return FfiConverterSequenceSequenceUByte.lift(
uniffiRustCall() { _status ->
UniffiLib.INSTANCE.uniffi_channel_fn_func_triple_ratchet_resize(
FfiConverterString.lower(`ratchetState`),FfiConverterString.lower(`other`),FfiConverterULong.lower(`id`),FfiConverterULong.lower(`total`),_status)
}
)
}
fun `verifyEd448`(`publicKey`: kotlin.String, `message`: kotlin.String, `signature`: kotlin.String): kotlin.String {
return FfiConverterString.lift(
uniffiRustCall() { _status ->

View File

@ -823,6 +823,101 @@ public func FfiConverterTypeTripleRatchetStateAndMetadata_lower(_ value: TripleR
return FfiConverterTypeTripleRatchetStateAndMetadata.lower(value)
}
public enum CryptoError {
case InvalidState(message: String)
case InvalidEnvelope(message: String)
case DecryptionFailed(message: String)
case EncryptionFailed(message: String)
case SerializationFailed(message: String)
case InvalidInput(message: String)
}
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeCryptoError: FfiConverterRustBuffer {
typealias SwiftType = CryptoError
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> CryptoError {
let variant: Int32 = try readInt(&buf)
switch variant {
case 1: return .InvalidState(
message: try FfiConverterString.read(from: &buf)
)
case 2: return .InvalidEnvelope(
message: try FfiConverterString.read(from: &buf)
)
case 3: return .DecryptionFailed(
message: try FfiConverterString.read(from: &buf)
)
case 4: return .EncryptionFailed(
message: try FfiConverterString.read(from: &buf)
)
case 5: return .SerializationFailed(
message: try FfiConverterString.read(from: &buf)
)
case 6: return .InvalidInput(
message: try FfiConverterString.read(from: &buf)
)
default: throw UniffiInternalError.unexpectedEnumCase
}
}
public static func write(_ value: CryptoError, into buf: inout [UInt8]) {
switch value {
case .InvalidState(_ /* message is ignored*/):
writeInt(&buf, Int32(1))
case .InvalidEnvelope(_ /* message is ignored*/):
writeInt(&buf, Int32(2))
case .DecryptionFailed(_ /* message is ignored*/):
writeInt(&buf, Int32(3))
case .EncryptionFailed(_ /* message is ignored*/):
writeInt(&buf, Int32(4))
case .SerializationFailed(_ /* message is ignored*/):
writeInt(&buf, Int32(5))
case .InvalidInput(_ /* message is ignored*/):
writeInt(&buf, Int32(6))
}
}
}
extension CryptoError: Equatable, Hashable {}
extension CryptoError: Foundation.LocalizedError {
public var errorDescription: String? {
String(reflecting: self)
}
}
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
@ -905,15 +1000,15 @@ public func decryptInboxMessage(input: String) -> String {
)
})
}
public func doubleRatchetDecrypt(ratchetStateAndEnvelope: DoubleRatchetStateAndEnvelope) -> DoubleRatchetStateAndMessage {
return try! FfiConverterTypeDoubleRatchetStateAndMessage.lift(try! rustCall() {
public func doubleRatchetDecrypt(ratchetStateAndEnvelope: DoubleRatchetStateAndEnvelope)throws -> DoubleRatchetStateAndMessage {
return try FfiConverterTypeDoubleRatchetStateAndMessage.lift(try rustCallWithError(FfiConverterTypeCryptoError.lift) {
uniffi_channel_fn_func_double_ratchet_decrypt(
FfiConverterTypeDoubleRatchetStateAndEnvelope.lower(ratchetStateAndEnvelope),$0
)
})
}
public func doubleRatchetEncrypt(ratchetStateAndMessage: DoubleRatchetStateAndMessage) -> DoubleRatchetStateAndEnvelope {
return try! FfiConverterTypeDoubleRatchetStateAndEnvelope.lift(try! rustCall() {
public func doubleRatchetEncrypt(ratchetStateAndMessage: DoubleRatchetStateAndMessage)throws -> DoubleRatchetStateAndEnvelope {
return try FfiConverterTypeDoubleRatchetStateAndEnvelope.lift(try rustCallWithError(FfiConverterTypeCryptoError.lift) {
uniffi_channel_fn_func_double_ratchet_encrypt(
FfiConverterTypeDoubleRatchetStateAndMessage.lower(ratchetStateAndMessage),$0
)
@ -1006,48 +1101,58 @@ public func signEd448(key: String, message: String) -> String {
)
})
}
public func tripleRatchetDecrypt(ratchetStateAndEnvelope: TripleRatchetStateAndEnvelope) -> TripleRatchetStateAndMessage {
return try! FfiConverterTypeTripleRatchetStateAndMessage.lift(try! rustCall() {
public func tripleRatchetDecrypt(ratchetStateAndEnvelope: TripleRatchetStateAndEnvelope)throws -> TripleRatchetStateAndMessage {
return try FfiConverterTypeTripleRatchetStateAndMessage.lift(try rustCallWithError(FfiConverterTypeCryptoError.lift) {
uniffi_channel_fn_func_triple_ratchet_decrypt(
FfiConverterTypeTripleRatchetStateAndEnvelope.lower(ratchetStateAndEnvelope),$0
)
})
}
public func tripleRatchetEncrypt(ratchetStateAndMessage: TripleRatchetStateAndMessage) -> TripleRatchetStateAndEnvelope {
return try! FfiConverterTypeTripleRatchetStateAndEnvelope.lift(try! rustCall() {
public func tripleRatchetEncrypt(ratchetStateAndMessage: TripleRatchetStateAndMessage)throws -> TripleRatchetStateAndEnvelope {
return try FfiConverterTypeTripleRatchetStateAndEnvelope.lift(try rustCallWithError(FfiConverterTypeCryptoError.lift) {
uniffi_channel_fn_func_triple_ratchet_encrypt(
FfiConverterTypeTripleRatchetStateAndMessage.lower(ratchetStateAndMessage),$0
)
})
}
public func tripleRatchetInitRound1(ratchetStateAndMetadata: TripleRatchetStateAndMetadata) -> TripleRatchetStateAndMetadata {
return try! FfiConverterTypeTripleRatchetStateAndMetadata.lift(try! rustCall() {
public func tripleRatchetInitRound1(ratchetStateAndMetadata: TripleRatchetStateAndMetadata)throws -> TripleRatchetStateAndMetadata {
return try FfiConverterTypeTripleRatchetStateAndMetadata.lift(try rustCallWithError(FfiConverterTypeCryptoError.lift) {
uniffi_channel_fn_func_triple_ratchet_init_round_1(
FfiConverterTypeTripleRatchetStateAndMetadata.lower(ratchetStateAndMetadata),$0
)
})
}
public func tripleRatchetInitRound2(ratchetStateAndMetadata: TripleRatchetStateAndMetadata) -> TripleRatchetStateAndMetadata {
return try! FfiConverterTypeTripleRatchetStateAndMetadata.lift(try! rustCall() {
public func tripleRatchetInitRound2(ratchetStateAndMetadata: TripleRatchetStateAndMetadata)throws -> TripleRatchetStateAndMetadata {
return try FfiConverterTypeTripleRatchetStateAndMetadata.lift(try rustCallWithError(FfiConverterTypeCryptoError.lift) {
uniffi_channel_fn_func_triple_ratchet_init_round_2(
FfiConverterTypeTripleRatchetStateAndMetadata.lower(ratchetStateAndMetadata),$0
)
})
}
public func tripleRatchetInitRound3(ratchetStateAndMetadata: TripleRatchetStateAndMetadata) -> TripleRatchetStateAndMetadata {
return try! FfiConverterTypeTripleRatchetStateAndMetadata.lift(try! rustCall() {
public func tripleRatchetInitRound3(ratchetStateAndMetadata: TripleRatchetStateAndMetadata)throws -> TripleRatchetStateAndMetadata {
return try FfiConverterTypeTripleRatchetStateAndMetadata.lift(try rustCallWithError(FfiConverterTypeCryptoError.lift) {
uniffi_channel_fn_func_triple_ratchet_init_round_3(
FfiConverterTypeTripleRatchetStateAndMetadata.lower(ratchetStateAndMetadata),$0
)
})
}
public func tripleRatchetInitRound4(ratchetStateAndMetadata: TripleRatchetStateAndMetadata) -> TripleRatchetStateAndMetadata {
return try! FfiConverterTypeTripleRatchetStateAndMetadata.lift(try! rustCall() {
public func tripleRatchetInitRound4(ratchetStateAndMetadata: TripleRatchetStateAndMetadata)throws -> TripleRatchetStateAndMetadata {
return try FfiConverterTypeTripleRatchetStateAndMetadata.lift(try rustCallWithError(FfiConverterTypeCryptoError.lift) {
uniffi_channel_fn_func_triple_ratchet_init_round_4(
FfiConverterTypeTripleRatchetStateAndMetadata.lower(ratchetStateAndMetadata),$0
)
})
}
public func tripleRatchetResize(ratchetState: String, other: String, id: UInt64, total: UInt64) -> [[UInt8]] {
return try! FfiConverterSequenceSequenceUInt8.lift(try! rustCall() {
uniffi_channel_fn_func_triple_ratchet_resize(
FfiConverterString.lower(ratchetState),
FfiConverterString.lower(other),
FfiConverterUInt64.lower(id),
FfiConverterUInt64.lower(total),$0
)
})
}
public func verifyEd448(publicKey: String, message: String, signature: String) -> String {
return try! FfiConverterString.lift(try! rustCall() {
uniffi_channel_fn_func_verify_ed448(
@ -1076,10 +1181,10 @@ private var initializationResult: InitializationResult = {
if (uniffi_channel_checksum_func_decrypt_inbox_message() != 59344) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_channel_checksum_func_double_ratchet_decrypt() != 13335) {
if (uniffi_channel_checksum_func_double_ratchet_decrypt() != 59687) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_channel_checksum_func_double_ratchet_encrypt() != 59209) {
if (uniffi_channel_checksum_func_double_ratchet_encrypt() != 57909) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_channel_checksum_func_encrypt_inbox_message() != 48273) {
@ -1112,22 +1217,25 @@ private var initializationResult: InitializationResult = {
if (uniffi_channel_checksum_func_sign_ed448() != 28573) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_channel_checksum_func_triple_ratchet_decrypt() != 42324) {
if (uniffi_channel_checksum_func_triple_ratchet_decrypt() != 15842) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_channel_checksum_func_triple_ratchet_encrypt() != 61617) {
if (uniffi_channel_checksum_func_triple_ratchet_encrypt() != 23451) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_channel_checksum_func_triple_ratchet_init_round_1() != 42612) {
if (uniffi_channel_checksum_func_triple_ratchet_init_round_1() != 63112) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_channel_checksum_func_triple_ratchet_init_round_2() != 11875) {
if (uniffi_channel_checksum_func_triple_ratchet_init_round_2() != 34197) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_channel_checksum_func_triple_ratchet_init_round_3() != 50331) {
if (uniffi_channel_checksum_func_triple_ratchet_init_round_3() != 39476) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_channel_checksum_func_triple_ratchet_init_round_4() != 14779) {
if (uniffi_channel_checksum_func_triple_ratchet_init_round_4() != 19263) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_channel_checksum_func_triple_ratchet_resize() != 57124) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_channel_checksum_func_verify_ed448() != 57200) {

View File

@ -348,6 +348,11 @@ RustBuffer uniffi_channel_fn_func_triple_ratchet_init_round_3(RustBuffer ratchet
RustBuffer uniffi_channel_fn_func_triple_ratchet_init_round_4(RustBuffer ratchet_state_and_metadata, RustCallStatus *_Nonnull out_status
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_CHANNEL_FN_FUNC_TRIPLE_RATCHET_RESIZE
#define UNIFFI_FFIDEF_UNIFFI_CHANNEL_FN_FUNC_TRIPLE_RATCHET_RESIZE
RustBuffer uniffi_channel_fn_func_triple_ratchet_resize(RustBuffer ratchet_state, RustBuffer other, uint64_t id, uint64_t total, RustCallStatus *_Nonnull out_status
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_CHANNEL_FN_FUNC_VERIFY_ED448
#define UNIFFI_FFIDEF_UNIFFI_CHANNEL_FN_FUNC_VERIFY_ED448
RustBuffer uniffi_channel_fn_func_verify_ed448(RustBuffer public_key, RustBuffer message, RustBuffer signature, RustCallStatus *_Nonnull out_status
@ -745,6 +750,12 @@ uint16_t uniffi_channel_checksum_func_triple_ratchet_init_round_3(void
#define UNIFFI_FFIDEF_UNIFFI_CHANNEL_CHECKSUM_FUNC_TRIPLE_RATCHET_INIT_ROUND_4
uint16_t uniffi_channel_checksum_func_triple_ratchet_init_round_4(void
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_CHANNEL_CHECKSUM_FUNC_TRIPLE_RATCHET_RESIZE
#define UNIFFI_FFIDEF_UNIFFI_CHANNEL_CHECKSUM_FUNC_TRIPLE_RATCHET_RESIZE
uint16_t uniffi_channel_checksum_func_triple_ratchet_resize(void
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_CHANNEL_CHECKSUM_FUNC_VERIFY_ED448

View File

@ -16,6 +16,22 @@ pub(crate) mod protocols;
uniffi::include_scaffolding!("lib");
#[derive(Debug, thiserror::Error)]
pub enum CryptoError {
#[error("Invalid state: {0}")]
InvalidState(String),
#[error("Invalid envelope: {0}")]
InvalidEnvelope(String),
#[error("Decryption failed: {0}")]
DecryptionFailed(String),
#[error("Encryption failed: {0}")]
EncryptionFailed(String),
#[error("Serialization failed: {0}")]
SerializationFailed(String),
#[error("Invalid input: {0}")]
InvalidInput(String),
}
#[derive(Clone, PartialEq, Serialize, Deserialize)]
pub struct DoubleRatchetStateAndEnvelope {
pub ratchet_state: String,
@ -467,84 +483,45 @@ pub fn new_double_ratchet(session_key: &Vec<u8>, sending_header_key: &Vec<u8>, n
return json.unwrap();
}
pub fn double_ratchet_encrypt(ratchet_state_and_message: DoubleRatchetStateAndMessage) -> DoubleRatchetStateAndEnvelope {
pub fn double_ratchet_encrypt(ratchet_state_and_message: DoubleRatchetStateAndMessage) -> Result<DoubleRatchetStateAndEnvelope, CryptoError> {
let ratchet_state = ratchet_state_and_message.ratchet_state.clone();
let participant = DoubleRatchetParticipant::from_json(ratchet_state.clone());
let participant = DoubleRatchetParticipant::from_json(ratchet_state.clone())
.map_err(|e| CryptoError::InvalidState(e.to_string()))?;
if participant.is_err() {
return DoubleRatchetStateAndEnvelope{
ratchet_state: participant.unwrap_err().to_string(),
envelope: "".to_string(),
};
}
let mut dr = participant;
let envelope = dr.ratchet_encrypt(&ratchet_state_and_message.message)
.map_err(|e| CryptoError::EncryptionFailed(e.to_string()))?;
let mut dr = participant.unwrap();
let envelope = dr.ratchet_encrypt(&ratchet_state_and_message.message);
let participant_json = dr.to_json()
.map_err(|e| CryptoError::SerializationFailed(e.to_string()))?;
if envelope.is_err() {
return DoubleRatchetStateAndEnvelope{
ratchet_state: ratchet_state,
envelope: envelope.unwrap_err().to_string(),
};
}
let envelope_json = envelope.to_json()
.map_err(|e| CryptoError::SerializationFailed(e.to_string()))?;
let participant_json = dr.to_json();
if participant_json.is_err() {
return DoubleRatchetStateAndEnvelope{
ratchet_state: participant_json.unwrap_err().to_string(),
envelope: "".to_string(),
};
}
let envelope_json = envelope.unwrap().to_json();
if envelope_json.is_err() {
return DoubleRatchetStateAndEnvelope{
ratchet_state: ratchet_state,
envelope: envelope_json.unwrap_err().to_string(),
};
}
return DoubleRatchetStateAndEnvelope{
ratchet_state: participant_json.unwrap(),
envelope: envelope_json.unwrap(),
};
Ok(DoubleRatchetStateAndEnvelope{
ratchet_state: participant_json,
envelope: envelope_json,
})
}
pub fn double_ratchet_decrypt(ratchet_state_and_envelope: DoubleRatchetStateAndEnvelope) -> DoubleRatchetStateAndMessage {
pub fn double_ratchet_decrypt(ratchet_state_and_envelope: DoubleRatchetStateAndEnvelope) -> Result<DoubleRatchetStateAndMessage, CryptoError> {
let ratchet_state = ratchet_state_and_envelope.ratchet_state.clone();
let participant = DoubleRatchetParticipant::from_json(ratchet_state.clone());
let envelope = P2PChannelEnvelope::from_json(ratchet_state_and_envelope.envelope);
let participant = DoubleRatchetParticipant::from_json(ratchet_state.clone())
.map_err(|e| CryptoError::InvalidState(e.to_string()))?;
let envelope = P2PChannelEnvelope::from_json(ratchet_state_and_envelope.envelope)
.map_err(|e| CryptoError::InvalidEnvelope(e.to_string()))?;
if participant.is_err() || envelope.is_err() {
return DoubleRatchetStateAndMessage{
ratchet_state: ratchet_state,
message: vec![],
};
}
let mut dr = participant;
let message = dr.ratchet_decrypt(&envelope)
.map_err(|e| CryptoError::DecryptionFailed(e.to_string()))?;
let mut dr = participant.unwrap();
let message = dr.ratchet_decrypt(&envelope.unwrap());
let participant_json = dr.to_json()
.map_err(|e| CryptoError::SerializationFailed(e.to_string()))?;
if message.is_err() {
return DoubleRatchetStateAndMessage{
ratchet_state: ratchet_state,
message: message.unwrap_err().to_string().as_bytes().to_vec(),
};
}
let participant_json = dr.to_json();
if participant_json.is_err() {
return DoubleRatchetStateAndMessage{
ratchet_state: participant_json.unwrap_err().to_string(),
message: vec![],
};
}
return DoubleRatchetStateAndMessage{
ratchet_state: participant_json.unwrap(),
message: message.unwrap(),
};
Ok(DoubleRatchetStateAndMessage{
ratchet_state: participant_json,
message: message,
})
}
pub fn new_triple_ratchet(peers: &Vec<Vec<u8>>, peer_key: &Vec<u8>, identity_key: &Vec<u8>, signed_pre_key: &Vec<u8>, threshold: u64, async_dkg_ratchet: bool) -> TripleRatchetStateAndMetadata {
@ -688,287 +665,178 @@ fn json_to_metadata(ratchet_state_and_metadata: TripleRatchetStateAndMetadata, r
Ok(metadata)
}
pub fn triple_ratchet_init_round_1(ratchet_state_and_metadata: TripleRatchetStateAndMetadata) -> TripleRatchetStateAndMetadata {
let ratchet_state = ratchet_state_and_metadata.ratchet_state.clone();
let tr = TripleRatchetParticipant::from_json(&ratchet_state);
if tr.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: tr.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
let metadata = match json_to_metadata(ratchet_state_and_metadata, &ratchet_state) {
Ok(value) => value,
Err(value) => return value,
};
let mut trp = tr.unwrap();
let result = trp.initialize(&metadata);
if result.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: result.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
let metadata = result.unwrap();
let metadata_json = match metadata_to_json(&ratchet_state, metadata) {
Ok(value) => value,
Err(value) => return value,
};
let json = trp.to_json();
if json.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: json.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
return TripleRatchetStateAndMetadata{
ratchet_state: json.unwrap(),
metadata: metadata_json,
};
fn json_to_metadata_result(ratchet_state_and_metadata: TripleRatchetStateAndMetadata, _ratchet_state: &String) -> Result<HashMap<Vec<u8>, P2PChannelEnvelope>, CryptoError> {
let mut metadata = HashMap::<Vec<u8>, P2PChannelEnvelope>::new();
for (k,v) in ratchet_state_and_metadata.metadata {
let env = P2PChannelEnvelope::from_json(v)
.map_err(|e| CryptoError::InvalidEnvelope(e.to_string()))?;
let kb = BASE64_STANDARD.decode(k)
.map_err(|e| CryptoError::InvalidInput(e.to_string()))?;
metadata.insert(kb, env);
}
Ok(metadata)
}
pub fn triple_ratchet_init_round_2(ratchet_state_and_metadata: TripleRatchetStateAndMetadata) -> TripleRatchetStateAndMetadata {
let ratchet_state = ratchet_state_and_metadata.ratchet_state.clone();
let tr = TripleRatchetParticipant::from_json(&ratchet_state);
if tr.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: tr.err().unwrap().to_string(),
metadata: HashMap::new(),
};
fn metadata_to_json_result(_ratchet_state: &String, metadata: HashMap<Vec<u8>, P2PChannelEnvelope>) -> Result<HashMap<String, String>, CryptoError> {
let mut metadata_json = HashMap::<String, String>::new();
for (k,v) in metadata {
let env = v.to_json()
.map_err(|e| CryptoError::SerializationFailed(e.to_string()))?;
metadata_json.insert(BASE64_STANDARD.encode(k), env);
}
Ok(metadata_json)
}
let metadata = match json_to_metadata(ratchet_state_and_metadata, &ratchet_state) {
Ok(value) => value,
Err(value) => return value,
};
pub fn triple_ratchet_init_round_1(ratchet_state_and_metadata: TripleRatchetStateAndMetadata) -> Result<TripleRatchetStateAndMetadata, CryptoError> {
let ratchet_state = ratchet_state_and_metadata.ratchet_state.clone();
let tr = TripleRatchetParticipant::from_json(&ratchet_state)
.map_err(|e| CryptoError::InvalidState(e.to_string()))?;
let mut trp = tr.unwrap();
let metadata = json_to_metadata_result(ratchet_state_and_metadata, &ratchet_state)?;
let mut trp = tr;
let result = trp.initialize(&metadata)
.map_err(|e| CryptoError::InvalidInput(e.to_string()))?;
let metadata_json = metadata_to_json_result(&ratchet_state, result)?;
let json = trp.to_json()
.map_err(|e| CryptoError::SerializationFailed(e.to_string()))?;
Ok(TripleRatchetStateAndMetadata{
ratchet_state: json,
metadata: metadata_json,
})
}
pub fn triple_ratchet_init_round_2(ratchet_state_and_metadata: TripleRatchetStateAndMetadata) -> Result<TripleRatchetStateAndMetadata, CryptoError> {
let ratchet_state = ratchet_state_and_metadata.ratchet_state.clone();
let tr = TripleRatchetParticipant::from_json(&ratchet_state)
.map_err(|e| CryptoError::InvalidState(e.to_string()))?;
let metadata = json_to_metadata_result(ratchet_state_and_metadata, &ratchet_state)?;
let mut trp = tr;
let mut result = HashMap::<Vec<u8>, P2PChannelEnvelope>::new();
for (k, v) in metadata {
let r = trp.receive_poly_frag(&k, &v);
if r.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: r.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
let r = trp.receive_poly_frag(&k, &v)
.map_err(|e| CryptoError::InvalidInput(e.to_string()))?;
let opt = r.unwrap();
if opt.is_some() {
result = opt.unwrap();
if let Some(out) = r {
result = out;
}
}
let metadata_json = match metadata_to_json(&ratchet_state, result) {
Ok(value) => value,
Err(value) => return value,
};
let metadata_json = metadata_to_json_result(&ratchet_state, result)?;
let json = trp.to_json();
if json.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: json.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
let json = trp.to_json()
.map_err(|e| CryptoError::SerializationFailed(e.to_string()))?;
return TripleRatchetStateAndMetadata{
ratchet_state: json.unwrap(),
Ok(TripleRatchetStateAndMetadata{
ratchet_state: json,
metadata: metadata_json,
};
})
}
pub fn triple_ratchet_init_round_3(ratchet_state_and_metadata: TripleRatchetStateAndMetadata) -> TripleRatchetStateAndMetadata {
pub fn triple_ratchet_init_round_3(ratchet_state_and_metadata: TripleRatchetStateAndMetadata) -> Result<TripleRatchetStateAndMetadata, CryptoError> {
let ratchet_state = ratchet_state_and_metadata.ratchet_state.clone();
let tr = TripleRatchetParticipant::from_json(&ratchet_state);
if tr.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: tr.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
let tr = TripleRatchetParticipant::from_json(&ratchet_state)
.map_err(|e| CryptoError::InvalidState(e.to_string()))?;
let metadata = match json_to_metadata(ratchet_state_and_metadata, &ratchet_state) {
Ok(value) => value,
Err(value) => return value,
};
let metadata = json_to_metadata_result(ratchet_state_and_metadata, &ratchet_state)?;
let mut trp = tr.unwrap();
let mut trp = tr;
let mut result = HashMap::<Vec<u8>, P2PChannelEnvelope>::new();
for (k, v) in metadata {
let r = trp.receive_commitment(&k, &v);
if r.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: r.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
let r = trp.receive_commitment(&k, &v)
.map_err(|e| CryptoError::InvalidInput(e.to_string()))?;
let opt = r.unwrap();
if opt.is_some() {
result = opt.unwrap();
if let Some(out) = r {
result = out;
}
}
let metadata_json = match metadata_to_json(&ratchet_state, result) {
Ok(value) => value,
Err(value) => return value,
};
let metadata_json = metadata_to_json_result(&ratchet_state, result)?;
let json = trp.to_json();
if json.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: json.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
let json = trp.to_json()
.map_err(|e| CryptoError::SerializationFailed(e.to_string()))?;
return TripleRatchetStateAndMetadata{
ratchet_state: json.unwrap(),
Ok(TripleRatchetStateAndMetadata{
ratchet_state: json,
metadata: metadata_json,
};
})
}
pub fn triple_ratchet_init_round_4(ratchet_state_and_metadata: TripleRatchetStateAndMetadata) -> TripleRatchetStateAndMetadata {
pub fn triple_ratchet_init_round_4(ratchet_state_and_metadata: TripleRatchetStateAndMetadata) -> Result<TripleRatchetStateAndMetadata, CryptoError> {
let ratchet_state = ratchet_state_and_metadata.ratchet_state.clone();
let tr = TripleRatchetParticipant::from_json(&ratchet_state);
if tr.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: tr.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
let tr = TripleRatchetParticipant::from_json(&ratchet_state)
.map_err(|e| CryptoError::InvalidState(e.to_string()))?;
let metadata = match json_to_metadata(ratchet_state_and_metadata, &ratchet_state) {
Ok(value) => value,
Err(value) => return value,
};
let metadata = json_to_metadata_result(ratchet_state_and_metadata, &ratchet_state)?;
let mut trp = tr.unwrap();
let mut result = HashMap::<Vec<u8>, P2PChannelEnvelope>::new();
let mut trp = tr;
let result = HashMap::<Vec<u8>, P2PChannelEnvelope>::new();
for (k, v) in metadata {
let r = trp.recombine(&k, &v);
if r.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: r.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
trp.recombine(&k, &v)
.map_err(|e| CryptoError::InvalidInput(e.to_string()))?;
}
let metadata_json = match metadata_to_json(&ratchet_state, result) {
Ok(value) => value,
Err(value) => return value,
};
let metadata_json = metadata_to_json_result(&ratchet_state, result)?;
let json = trp.to_json();
if json.is_err() {
return TripleRatchetStateAndMetadata{
ratchet_state: json.err().unwrap().to_string(),
metadata: HashMap::new(),
};
}
let json = trp.to_json()
.map_err(|e| CryptoError::SerializationFailed(e.to_string()))?;
return TripleRatchetStateAndMetadata{
ratchet_state: json.unwrap(),
Ok(TripleRatchetStateAndMetadata{
ratchet_state: json,
metadata: metadata_json,
};
})
}
pub fn triple_ratchet_encrypt(ratchet_state_and_message: TripleRatchetStateAndMessage) -> TripleRatchetStateAndEnvelope {
pub fn triple_ratchet_encrypt(ratchet_state_and_message: TripleRatchetStateAndMessage) -> Result<TripleRatchetStateAndEnvelope, CryptoError> {
let ratchet_state = ratchet_state_and_message.ratchet_state.clone();
let tr = TripleRatchetParticipant::from_json(&ratchet_state);
if tr.is_err() {
return TripleRatchetStateAndEnvelope{
ratchet_state: tr.err().unwrap().to_string(),
envelope: "".to_string(),
};
}
let tr = TripleRatchetParticipant::from_json(&ratchet_state)
.map_err(|e| CryptoError::InvalidState(e.to_string()))?;
let mut trp = tr.unwrap();
let result = trp.ratchet_encrypt(&ratchet_state_and_message.message);
let mut trp = tr;
let envelope = trp.ratchet_encrypt(&ratchet_state_and_message.message)
.map_err(|e| CryptoError::EncryptionFailed(e.to_string()))?;
if result.is_err() {
return TripleRatchetStateAndEnvelope{
ratchet_state: result.err().unwrap().to_string(),
envelope: "".to_string(),
};
}
let envelope_json = envelope.to_json()
.map_err(|e| CryptoError::SerializationFailed(e.to_string()))?;
let envelope = result.unwrap();
let envelope_json = envelope.to_json();
let json = trp.to_json()
.map_err(|e| CryptoError::SerializationFailed(e.to_string()))?;
if envelope_json.is_err() {
return TripleRatchetStateAndEnvelope{
ratchet_state: envelope_json.err().unwrap().to_string(),
envelope: "".to_string(),
};
}
let json = trp.to_json();
if json.is_err() {
return TripleRatchetStateAndEnvelope{
ratchet_state: json.err().unwrap().to_string(),
envelope: "".to_string(),
};
}
return TripleRatchetStateAndEnvelope{
ratchet_state: json.unwrap(),
envelope: envelope_json.unwrap(),
};
Ok(TripleRatchetStateAndEnvelope{
ratchet_state: json,
envelope: envelope_json,
})
}
pub fn triple_ratchet_decrypt(ratchet_state_and_envelope: TripleRatchetStateAndEnvelope) -> TripleRatchetStateAndMessage {
pub fn triple_ratchet_decrypt(ratchet_state_and_envelope: TripleRatchetStateAndEnvelope) -> Result<TripleRatchetStateAndMessage, CryptoError> {
let ratchet_state = ratchet_state_and_envelope.ratchet_state.clone();
let tr = TripleRatchetParticipant::from_json(&ratchet_state);
if tr.is_err() {
return TripleRatchetStateAndMessage{
ratchet_state: tr.err().unwrap().to_string(),
message: vec![],
};
}
let tr = TripleRatchetParticipant::from_json(&ratchet_state)
.map_err(|e| CryptoError::InvalidState(e.to_string()))?;
let mut trp = tr.unwrap();
let env = P2PChannelEnvelope::from_json(ratchet_state_and_envelope.envelope);
if env.is_err() {
return TripleRatchetStateAndMessage{
ratchet_state: env.err().unwrap().to_string(),
message: vec![],
};
}
let mut trp = tr;
let env = P2PChannelEnvelope::from_json(ratchet_state_and_envelope.envelope)
.map_err(|e| CryptoError::InvalidEnvelope(e.to_string()))?;
let result = trp.ratchet_decrypt(&env.unwrap());
let result = trp.ratchet_decrypt(&env)
.map_err(|e| CryptoError::DecryptionFailed(e.to_string()))?;
if result.is_err() {
return TripleRatchetStateAndMessage{
ratchet_state: result.err().unwrap().to_string(),
message: vec![],
};
}
let message = result.0;
let message = result.unwrap().0;
let json = trp.to_json()
.map_err(|e| CryptoError::SerializationFailed(e.to_string()))?;
let json = trp.to_json();
if json.is_err() {
return TripleRatchetStateAndMessage{
ratchet_state: json.err().unwrap().to_string(),
message: vec![],
};
}
return TripleRatchetStateAndMessage{
ratchet_state: json.unwrap(),
Ok(TripleRatchetStateAndMessage{
ratchet_state: json,
message: message,
};
})
}
pub fn triple_ratchet_resize(ratchet_state: String, other: String, id: usize, total: usize) -> Vec<Vec<u8>> {
pub fn triple_ratchet_resize(ratchet_state: String, other: String, id: u64, total: u64) -> Vec<Vec<u8>> {
let tr = TripleRatchetParticipant::from_json(&ratchet_state);
if tr.is_err() {
return vec![vec![1]];
@ -979,7 +847,7 @@ pub fn triple_ratchet_resize(ratchet_state: String, other: String, id: usize, to
return vec![other_bytes.unwrap_err().to_string().as_bytes().to_vec()];
}
let result = tr.unwrap().ratchet_resize(other_bytes.unwrap(), id, total);
let result = tr.unwrap().ratchet_resize(other_bytes.unwrap(), id as usize, total as usize);
if result.is_err() {
return vec![result.unwrap_err().to_string().as_bytes().to_vec()];
}

View File

@ -19,17 +19,38 @@ namespace channel {
// Double Ratchet
string new_double_ratchet([ByRef] sequence<u8> session_key, [ByRef] sequence<u8> sending_header_key, [ByRef] sequence<u8> next_receiving_header_key, boolean is_sender, [ByRef] sequence<u8> sending_ephemeral_private_key, [ByRef] sequence<u8> receiving_ephemeral_key);
[Throws=CryptoError]
DoubleRatchetStateAndEnvelope double_ratchet_encrypt(DoubleRatchetStateAndMessage ratchet_state_and_message);
[Throws=CryptoError]
DoubleRatchetStateAndMessage double_ratchet_decrypt(DoubleRatchetStateAndEnvelope ratchet_state_and_envelope);
// Triple Ratchet
TripleRatchetStateAndMetadata new_triple_ratchet([ByRef] sequence<sequence<u8>> peers, [ByRef] sequence<u8> peer_key, [ByRef] sequence<u8> identity_key, [ByRef] sequence<u8> signed_pre_key, u64 threshold, boolean async_dkg_ratchet);
[Throws=CryptoError]
TripleRatchetStateAndMetadata triple_ratchet_init_round_1(TripleRatchetStateAndMetadata ratchet_state_and_metadata);
[Throws=CryptoError]
TripleRatchetStateAndMetadata triple_ratchet_init_round_2(TripleRatchetStateAndMetadata ratchet_state_and_metadata);
[Throws=CryptoError]
TripleRatchetStateAndMetadata triple_ratchet_init_round_3(TripleRatchetStateAndMetadata ratchet_state_and_metadata);
[Throws=CryptoError]
TripleRatchetStateAndMetadata triple_ratchet_init_round_4(TripleRatchetStateAndMetadata ratchet_state_and_metadata);
[Throws=CryptoError]
TripleRatchetStateAndEnvelope triple_ratchet_encrypt(TripleRatchetStateAndMessage ratchet_state_and_message);
[Throws=CryptoError]
TripleRatchetStateAndMessage triple_ratchet_decrypt(TripleRatchetStateAndEnvelope ratchet_state_and_envelope);
// Triple Ratchet Resize
sequence<sequence<u8>> triple_ratchet_resize(string ratchet_state, string other, u64 id, u64 total);
};
[Error]
enum CryptoError {
"InvalidState",
"InvalidEnvelope",
"DecryptionFailed",
"EncryptionFailed",
"SerializationFailed",
"InvalidInput",
};
dictionary DoubleRatchetStateAndEnvelope {

View File

@ -1521,7 +1521,7 @@ func (s *streamManager) walk(
// )
if len(lpref) > len(rpref) {
// s.logger.Debug("local prefix longer, traversing remote to path", pathString)
traverse := lpref[len(rpref):]
traverse := lpref[len(rpref)-1:]
rtrav := rnode
traversePath := append([]int32{}, rpref...)
for _, nibble := range traverse {
@ -1578,7 +1578,7 @@ func (s *streamManager) walk(
)
} else {
// s.logger.Debug("remote prefix longer, traversing local to path", pathString)
traverse := rpref[len(lpref):]
traverse := rpref[len(lpref)-1:]
ltrav := lnode
traversedPath := append([]int32{}, lnode.Path...)
@ -1626,9 +1626,12 @@ func (s *streamManager) walk(
); err != nil {
return errors.Wrap(err, "walk")
}
} else {
err := s.handleLeafData(incomingLeaves)
if err != nil {
return errors.Wrap(err, "walk")
}
}
// Client has extra data that server doesn't have
// Skip - pruning happens after sync completes
}
}
// If no child matched the nibble, the local tree doesn't extend
@ -1694,7 +1697,7 @@ func (s *streamManager) walk(
if (lchild != nil && rchild == nil) ||
(lchild == nil && rchild != nil) {
// s.logger.Info("branch divergence", pathString)
if lchild != nil && rchild == nil {
if lchild != nil {
// Local has a child that remote doesn't have
if isServer {
nextPath := append(
@ -1712,22 +1715,12 @@ func (s *streamManager) walk(
// Client has data server doesn't
// Skip - pruning happens after sync completes
}
if rchild != nil && lchild == nil {
// Remote has a child that local doesn't have
if isServer {
// Server doesn't have what client has - nothing to do
// Client will prune on their side
} else {
// Client doesn't have what server has - receive it
nextPath := append(
append([]int32{}, rpref...),
rchild.Index,
)
if rchild != nil {
if !isServer {
err := s.handleLeafData(incomingLeaves)
if err != nil {
return errors.Wrap(err, "walk")
}
_ = nextPath // path used by server's sendLeafData
}
}
} else {
@ -1741,10 +1734,21 @@ func (s *streamManager) walk(
nextPath,
)
if err != nil {
// s.logger.Debug("incomplete branch descension", zap.Error(err))
// Don't try to merge/prune on error - the connection may have failed
// and we don't want to delete local data based on incomplete info
return errors.Wrap(err, "walk")
s.logger.Info("incomplete branch descension", zap.Error(err))
if isServer {
if err := s.sendLeafData(
nextPath,
incomingLeaves,
); err != nil {
return errors.Wrap(err, "walk")
}
} else {
err := s.handleLeafData(incomingLeaves)
if err != nil {
return errors.Wrap(err, "walk")
}
}
continue
}
if err = s.walk(

View File

@ -44,6 +44,27 @@ func (e *GlobalConsensusEngine) ensureCoverageThresholds() {
haltGraceFrames = 360
}
// triggerCoverageCheckAsync starts a coverage check in a goroutine if one is
// not already in progress. This prevents blocking the event processing loop.
func (e *GlobalConsensusEngine) triggerCoverageCheckAsync(frameNumber uint64) {
// Skip if a coverage check is already in progress
if !e.coverageCheckInProgress.CompareAndSwap(false, true) {
e.logger.Debug(
"skipping coverage check, one already in progress",
zap.Uint64("frame_number", frameNumber),
)
return
}
go func() {
defer e.coverageCheckInProgress.Store(false)
if err := e.checkShardCoverage(frameNumber); err != nil {
e.logger.Error("failed to check shard coverage", zap.Error(err))
}
}()
}
// checkShardCoverage verifies coverage levels for all active shards
func (e *GlobalConsensusEngine) checkShardCoverage(frameNumber uint64) error {
e.ensureCoverageThresholds()

View File

@ -81,12 +81,8 @@ func (e *GlobalConsensusEngine) eventDistributorLoop(
e.flushDeferredGlobalMessages(data.Frame.GetRank() + 1)
// Check shard coverage
if err := e.checkShardCoverage(
data.Frame.Header.FrameNumber,
); err != nil {
e.logger.Error("failed to check shard coverage", zap.Error(err))
}
// Check shard coverage asynchronously to avoid blocking event processing
e.triggerCoverageCheckAsync(data.Frame.Header.FrameNumber)
// Update global coordination metrics
globalCoordinationTotal.Inc()

View File

@ -202,6 +202,7 @@ type GlobalConsensusEngine struct {
appFrameStoreMu sync.RWMutex
lowCoverageStreak map[string]*coverageStreak
proverOnlyMode atomic.Bool
coverageCheckInProgress atomic.Bool
peerInfoDigestCache map[string]struct{}
peerInfoDigestCacheMu sync.Mutex
keyRegistryDigestCache map[string]struct{}

View File

@ -1708,10 +1708,8 @@ func (e *GlobalConsensusEngine) addCertifiedState(
return
}
if err := e.checkShardCoverage(parent.State.GetFrameNumber()); err != nil {
e.logger.Error("could not check shard coverage", zap.Error(err))
return
}
// Trigger coverage check asynchronously to avoid blocking message processing
e.triggerCoverageCheckAsync(parent.State.GetFrameNumber())
}
func (e *GlobalConsensusEngine) handleProposal(message *pb.Message) {