0

I am building the back-end of an iOS crypto wallet app using FFI bridge between flutter and rust. In doing so, I am required to mirror the external types onto the rust input file, or api.rs when following the flutter_rust_bridge official. Here is the tutorial I have been following.

OFFICIAL DOC: flutter_rust_bridge -> for using 'external types'

Issue: Some of the structs, such as PublicKey, contain layers of nested structs or separately defined types which I assume all need to be mirrored as well. The crate containing these types is curve25519-dalek. In order to fully mirror the PublicKey, I need to re-export 2 private modules from the same crate. So far, I have been unsuccessful.

Here is the current error when running cargo check from root of the flutter>>rust;

error[E0433]: failed to resolve: use of undeclared crate or module `backend`
error[E0603]: module `backend` is private
error[E0603]: module `field` is private

I went through the relevant modules locally, in .cargo/registry/src... to try to make any necessary changes to data types visibility and by double-checking lib.rs for pub mod field/backend, but nothing has changed.

This is what I've written so far.

pub use curve25519_dalek::{
    edwards::{EdwardsPoint},
    ristretto::{CompressedRistretto, RistrettoPoint},
    scalar::{Scalar},
    backend::serial::u64::field::FieldElement51,
    field::FieldElement,
};
pub use schnorrkel::{
    keys::{
        Keypair, 
        SecretKey, 
        PublicKey
    },
    points::{RistrettoBoth},
    sign::{Signature},
};

// keypair
#[frb(mirror(Keypair))]
pub struct _Keypair {...}

// public key
#[frb(mirror(PublicKey))]
pub struct _PublicKey(pub (crate) RistrettoBoth);

...

#[frb(mirror(EdwardsPoint))]
pub struct _EdwardsPoint {
    pub(crate) X: FieldElement,
    pub(crate) Y: FieldElement,
    pub(crate) Z: FieldElement,
    pub(crate) T: FieldElement,
}

#[frb(mirror(FieldElement))] 
pub type _FieldElement = backend::serial::u64::field::FieldElement51;

#[frb(mirror(FieldElement51))] 
pub struct _FieldElement51(pub (crate) [u64; 5]);

Specifically I'd like advice on either or both;

  1. Would I be right to say that all nested data types need to be mirrored as well for FFI?
  2. Are there any other ways to approach the task of making modules public? What am I currently doing wrong?
kenta_desu
  • 303
  • 1
  • 9
  • I don't know `flutter_rust_bridge`, but generally any FFI should have some way of passing an “opaque” struct whose full definition is not known to the other language — which may need to be by pointer (`Box`) rather than value. That is likely a more appropriate solution than trying to access the private fields/types. – Kevin Reid Nov 06 '22 at 18:55
  • @KevinReid thank you, that approach does make a lot more sense. The word 'opaque' is also something I didn't know. However, I am having trouble imagining how that would be implemented for the definition - not implementation - of a struct. My elementary understanding was that the parameter to go in Box::new(_) needed to be a value rather than a data type, and thus a struct would need to be implemented before it can be passed via a Box. Do you know of any examples for this? – kenta_desu Nov 07 '22 at 05:31
  • 1
    Sorry, I was a little unclear. You can make a `Box` around a Rust value and then the only thing the other language needs to know about it the Box is it is pointer-sized. Depending on the exact FFI it might not work like that, or there might be a way to export a struct without exporting all its fields — all I'm saying is that trying to export a struct's entire private definition is probably not the only path. Again, I can't advise you about Dart/Flutter — which is why I didn't write an answer — but I hope these ideas can help you find a solution. – Kevin Reid Nov 07 '22 at 05:41

0 Answers0