Currently, the anoma-app-sdk arm-bindings crate is exporting bindings to instances of arm-risc0 types, and the actual resource construction logic is being defined in TypeScript . This means that resource logic is not only being duplicated across this repo and anomapay-backend, but also being defined here in TS instead of Rust, making it more difficult to audit and confirm that the TS logic matches the backend exactly.
NOTE See https://github.com/anoma/anomapay-backend/compare/main...justin/prove-feature-gate - this branch makes building to wasm32-unknown-unknown possible without affecting any previous simple_transfer builds/tests, and can provide TransferLogic & TransferLogicV2 to the SDK arm-bindings crate. FYI, this repo is not public for now, so we're discussing whether it can be published, the repo public, etc.
Since we have a Rust/wasm crate already, we could simply re-purpose the same methods from simple-transfer/transfer-lib in the backend, assuming we publish transfer-lib (and someday transfer-lib-v2) and import it here with the prove feature disabled. This will also streamline a move to TransferLogicV2, since we could build a new wasm in anoma-app-sdk supporting PA V2 as well as migrate_tx from crate.
This would ensure that Resource logic is defined in one place only. anoma-app-sdk would then only export any bindings needed by the front-end, instead of exporting bindings for every type of struct needed from arm-risc0. Instead of our Rust crate being specific to arm-bindings, we could move to a workspace with a structure like:
#
anoma-app-lib/
- arm-risc0-bindings/ # Formerly arm-bindings, be specific to the type of resource machine
- anomapay/ # Builders for simple_transfer/transfer_library
- anomapay-v2/ # Builders for simple_transfer/transfer_library_v2
...
Cargo.toml
We can keep any ARM bindings that may be needed by the front-end, but otherwise should move to a pure JS-Object/json API when interacting with Wasm functionality (we should consider nuking it entirely - our workspace could instead be comprised of simply a single crate for any given Anoma app along with version like above ^^, since ARM bindings are specific to an app). Instead of passing around references to wasm Rust-struct on the JS side, we simply use a JS-object/primitive based API to interact with the wasm.
Note that the namings are updated to indicate which Anoma application (i.e., which Anoma resource machine) the crate provides functionality for, as we can add additional apps in the future.
We can keep any ARM bindings that may be needed by the front-end, but otherwise should move to a pure JS-Object/json API when interacting with Wasm functionality (we should consider nuking it entirely - our workspace could instead be comprised of simply a single crate for any given Anoma app along with version like above ^^, since ARM bindings are specific to an app). Instead of passing around references to wasm Rust-struct instances for literally everything (Resource, Digest, NullifierKey, etc.), we use builder methods (which in turn incorporate methods from TransferLogic & TransferLogicV2) which provide the translation and bindings to the Rust types, and these methods accept JS-object params and return JS-objects. The wasm-bindgen output should be significantly smaller than what arm-bindings is currently producing.
Client
We should discuss the best way to introduce V2 to consumers of @anomaorg/anoma-app-sdk. My thoughts are as follows:
We could export our builders as ResourceBuilderV1 (and ResourceBuilderV2) (naming here is just an example!), with ResourceBuilderV1 re-exported as simply ResourceBuilder initially, then when V2 is required, set ResourceBuilder to ResourceBuilderV2 (breaking change, which is good) with ResourceBuilderV1 still available as an export as before. This would avoid having new clients needing to know which version is current - it should always just be ResourceBuilder.
// Re-export of ResourceBuilderV1 initially, later exporting ResourceBuilderV2
import { ResourceBuilder } from "@anomaorg/anoma-app-sdk/anomapay";
// PA v2 migration happens:
// ResourceBuilderV2 now available, but V1 is still available as well
import
ResourceBuilderV1,
ResourceBuilderV2,
} from "@anomaorg/anoma-app-sdk/anomapay";
Backend
One thing to consider is potential changes to backend Parameters - this is another area where the Rust / Wasm library could re-use functionality from the backend directly, provided the crate is published (eventually) and can support a wasm32-unknown-unknown build target (meaning risc0 prove feature is disabled).
Since Parameters is defined in simple_transfer/transfer_web, and to support all of the variants directly in wasm to be used by TypeScript could be complicated, this may be a case where we keep our current TypeScript definitions as is in TypeScript. We don't really need any of these methods, just the data type. The only caveat is we need to provide any V2 change, should they even be needed at all.
TODO
We currently cannot build using transfer_web as a dep, primarily because a wasm target cannot use or tolerate the system-level I/O stuff required by web-server, but libs exist within that crate defines types that are implemented (read duplicated) in the front-end, so perhaps these belong in a non-risc0 lib library, like transfer_web_lib (would add one more crate per each version though):
These seem particularly useful
Resources + witness data enum variant - Front-end uses an API defined in TypeScript to manually piece the witness data together. It potentially entirely duplicates something already defined and re-usable, provided it can be moved out of transfer_web, etc.
For now, make a branch on anomapay-backend and add to Cargo.toml to this git branch:
- Open branch that feature-gates anything that breaks by disabling
prove (transfer_lib, and any crates it imports from)
- Set up Cargo workspace to replace
arm-bindings, and move original arm-bindings into this (for now, it may become obsolete)
- Anoma App-specific dependencies should not be included in the root workspace
Cargo.toml as they are not shared
- Setup Resource builder bindings which incorporate resource construction logic
- Update build script to include crates under workspace, all as different
wasm-pack targets - ultimately, any client app integrating with Anoma will only include on wasm file which provides bindings for that particular app (anomapay only for now)
Currently, the
anoma-app-sdkarm-bindings crate is exporting bindings to instances ofarm-risc0types, and the actual resource construction logic is being defined in TypeScript . This means that resource logic is not only being duplicated across this repo and anomapay-backend, but also being defined here in TS instead of Rust, making it more difficult to audit and confirm that the TS logic matches the backend exactly.NOTE See https://github.com/anoma/anomapay-backend/compare/main...justin/prove-feature-gate - this branch makes building to
wasm32-unknown-unknownpossible without affecting any previoussimple_transferbuilds/tests, and can provideTransferLogic&TransferLogicV2to the SDKarm-bindingscrate. FYI, this repo is not public for now, so we're discussing whether it can be published, the repo public, etc.Since we have a Rust/wasm crate already, we could simply re-purpose the same methods from simple-transfer/transfer-lib in the backend, assuming we publish
transfer-lib(and somedaytransfer-lib-v2) and import it here with theprovefeature disabled. This will also streamline a move to TransferLogicV2, since we could build a new wasm inanoma-app-sdksupporting PA V2 as well asmigrate_txfrom crate.This would ensure that Resource logic is defined in one place only.
anoma-app-sdkwould then only export any bindings needed by the front-end, instead of exporting bindings for every type of struct needed fromarm-risc0. Instead of our Rust crate being specific toarm-bindings, we could move to a workspace with a structure like:We can keep any ARM bindings that may be needed by the front-end, but otherwise should move to a pure JS-Object/json API when interacting with Wasm functionality (we should consider nuking it entirely - our workspace could instead be comprised of simply a single crate for any given Anoma app along with version like above ^^, since ARM bindings are specific to an app). Instead of passing around references to wasm Rust-struct on the JS side, we simply use a JS-object/primitive based API to interact with the wasm.
Note that the namings are updated to indicate which Anoma application (i.e., which Anoma resource machine) the crate provides functionality for, as we can add additional apps in the future.
We can keep any ARM bindings that may be needed by the front-end, but otherwise should move to a pure JS-Object/json API when interacting with Wasm functionality (we should consider nuking it entirely - our workspace could instead be comprised of simply a single crate for any given Anoma app along with version like above ^^, since ARM bindings are specific to an app). Instead of passing around references to wasm Rust-struct instances for literally everything (
Resource,Digest,NullifierKey, etc.), we use builder methods (which in turn incorporate methods fromTransferLogic&TransferLogicV2) which provide the translation and bindings to the Rust types, and these methods accept JS-object params and return JS-objects. Thewasm-bindgenoutput should be significantly smaller than whatarm-bindingsis currently producing.Client
We should discuss the best way to introduce V2 to consumers of
@anomaorg/anoma-app-sdk. My thoughts are as follows:We could export our builders as
ResourceBuilderV1(andResourceBuilderV2) (naming here is just an example!), withResourceBuilderV1re-exported as simplyResourceBuilderinitially, then when V2 is required, setResourceBuildertoResourceBuilderV2(breaking change, which is good) withResourceBuilderV1still available as an export as before. This would avoid having new clients needing to know which version is current - it should always just beResourceBuilder.Backend
One thing to consider is potential changes to backend
Parameters- this is another area where the Rust / Wasm library could re-use functionality from the backend directly, provided the crate is published (eventually) and can support awasm32-unknown-unknownbuild target (meaningrisc0provefeature is disabled).Since Parameters is defined in
simple_transfer/transfer_web, and to support all of the variants directly in wasm to be used by TypeScript could be complicated, this may be a case where we keep our current TypeScript definitions as is in TypeScript. We don't really need any of these methods, just the data type. The only caveat is we need to provide any V2 change, should they even be needed at all.TODO
We currently cannot build using
transfer_webas a dep, primarily because a wasm target cannot use or tolerate the system-level I/O stuff required by web-server, but libs exist within that crate defines types that are implemented (read duplicated) in the front-end, so perhaps these belong in a non-risc0 lib library, liketransfer_web_lib(would add one more crate per each version though):These seem particularly useful
Resources + witness data enum variant - Front-end uses an API defined in TypeScript to manually piece the witness data together. It potentially entirely duplicates something already defined and re-usable, provided it can be moved out of
transfer_web, etc.For now, make a branch on anomapay-backend and add to
Cargo.tomlto this git branch:prove(transfer_lib, and any crates it imports from)arm-bindings, and move originalarm-bindingsinto this (for now, it may become obsolete)Cargo.tomlas they are not sharedwasm-packtargets - ultimately, any client app integrating with Anoma will only include on wasm file which provides bindings for that particular app (anomapayonly for now)