Skip to content

Commit

Permalink
Make all HelloWorld resources have the same kind (#25)
Browse files Browse the repository at this point in the history
* Set webpack config to production

* Wrap the result of fetchBinary in a Uint8Array

* Make all HelloWorld resources have the same kind

The HelloWorld message is now stored in the value instead of the label.

Messages are retrieved using the `filterKind` endpoint of the BlockService

* Add filterKind API to AnomaClient

* Use the filter kind method in the HelloWorld webapp

* Fix HelloWorld test script

* Restore catch handler

* Add comment to explain dummyResource
  • Loading branch information
paulcadman authored Jan 23, 2025
1 parent f9230d1 commit 6132630
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 23 deletions.
26 changes: 26 additions & 0 deletions HelloWorld/AppIdentity.juvix
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module AppIdentity;

import Stdlib.Prelude open;
import Applib open;

--- The label for HelloWorld resources
label : Nat := builtinAnomaEncode "HelloWorld";

--- Compute the kind of the HelloWorld ;Resource;
main (encodedLogic : Encoded Logic) : Kind :=
let
logic := Encode.decode encodedLogic;
-- Only the logic and label are used in the kind computation, we can use
-- default values for other fields.
dummyResource : Resource :=
mkResource@{
label;
logic;
value := 0;
quantity := 0;
nonce := 0;
ephemeral := true;
randSeed := 0;
nullifierKeyCommitment := 0;
};
in kind dummyResource;
2 changes: 1 addition & 1 deletion HelloWorld/GetMessage.juvix
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ import Applib open;

--- Extract the message from a HelloWorld ;Resource;
main (encodedResource : Nat) : String :=
encodedResource |> builtinAnomaDecode |> Resource.label |> builtinAnomaDecode;
encodedResource |> builtinAnomaDecode |> Resource.value |> builtinAnomaDecode;
25 changes: 15 additions & 10 deletions HelloWorld/HelloWorld.juvix
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@ module HelloWorld;

import Stdlib.Prelude open;
import Applib open;

--- A logic function that is always valid.
logic (publicInputs : Instance) (privateInputs : Witness) : Bool := true;
import AppIdentity open using {label};

--- Creates a new ;Resource; that stores a ;String; message.
--- @param nonce A number used to ensure resource uniqueness
--- @param message The message to store in the ;Resource;.
mkHelloWorldResource
(nonce : Nat) (message : String) {ephemeral : Bool := false} : Resource :=
(logic : Logic)
(nonce : Nat)
(message : String)
{ephemeral : Bool := false}
: Resource :=
mkResource@{
label := builtinAnomaEncode message;
label;
logic;
value := 0;
value := builtinAnomaEncode message;
quantity := 1;
nonce;
ephemeral;
Expand All @@ -29,12 +31,13 @@ helloWorldTransaction
{M : Type -> Type}
{{Monad M}}
{{Tx M}}
(logic : Logic)
(nonce : Nat)
(label : String)
(message : String)
: M Transaction :=
do {
let
newResource := mkHelloWorldResource nonce label;
newResource := mkHelloWorldResource logic nonce message;
in
prepareStandardTransaction@{
-- A Transaction must be balanced, so we consume an ephemeral resource of
Expand All @@ -51,5 +54,7 @@ ctx : TxContext :=
};

--- The function that is run to produce a Transaction to send to Anoma.
main (message : String) : TransactionRequest :=
buildTransactionRequest 0 ctx (helloWorldTransaction 0 message);
main (encodedLogic : Encoded Logic) (message : String) : TransactionRequest :=
let
logic : Logic := Encode.decode encodedLogic;
in buildTransactionRequest 0 ctx (helloWorldTransaction logic 0 message);
18 changes: 18 additions & 0 deletions HelloWorld/Logic.juvix
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module Logic;

import Stdlib.Prelude open;
import Applib open;

--- A logic function that is always valid.
logic (publicInputs : Instance) (privateInputs : Witness) : Bool := true;

type LogicWrapper :=
mkLogicWrapper@{
logic : Logic;
};

--- Compute the logic function for the HelloWorld ;Resource;
main : LogicWrapper :=
mkLogicWrapper@{
logic;
};
56 changes: 52 additions & 4 deletions HelloWorld/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ ANOMA_PATH ?= $(error set the ANOMA_PATH variable to a path to an anoma clone)
base-path = .
base = HelloWorld
get-message = GetMessage
kind = AppIdentity
logic = Logic
message ?= "hello world\n"

anoma-build-dir = anoma-build
Expand All @@ -25,6 +27,12 @@ config = $(anoma-build-dir)/config.yaml
temp-file := $(anoma-build-dir)/temp_line
message-file = $(anoma-build-dir)/message

kind-juvix = $(base-path)/$(kind).juvix
kind-nockma = $(anoma-build-dir)/$(kind).nockma
kind-proved = $(anoma-build-dir)/$(kind).proved.nockma
kind-proved-cued = $(anoma-build-dir)/$(kind).cued.nockma
kind-proved-cued-b64 = $(anoma-build-dir)/$(kind).cued.nockma.b64

juvix = $(base-path)/$(base).juvix
nockma = $(anoma-build-dir)/$(base).nockma
proved = $(anoma-build-dir)/$(base).proved.nockma
Expand All @@ -33,6 +41,12 @@ get-message-juvix = $(base-path)/$(get-message).juvix
get-message-nockma = $(anoma-build-dir)/$(get-message).nockma
get-message-proved = $(anoma-build-dir)/$(get-message).proved.nockma

logic-juvix = $(base-path)/$(logic).juvix
logic-nockma = $(anoma-build-dir)/$(logic).nockma
logic-proved = $(anoma-build-dir)/$(logic).proved.nockma

filter-request = $(anoma-build-dir)/filter-request.json

unspent-resources = $(anoma-build-dir)/unspent-resources
last-message-txt = $(anoma-build-dir)/last-message.txt

Expand Down Expand Up @@ -79,6 +93,12 @@ compile-add-message: $(nockma)
.PHONY: compile-get-message
compile-get-message: $(get-message-nockma)

.PHONY: compile-logic
compile-logic: $(logic-proved)

.PHONY: compute-kind
compute-kind: $(kind-proved-cued)

.PHONY: add-transaction
add-transaction: $(proved) $(config)
@juvix dev anoma -c $(config) add-transaction $(proved)
Expand All @@ -105,15 +125,43 @@ get-all-messages: $(get-message-nockma) $(config) $(unspent-resources)
$(nockma): $(juvix) $(anoma-build)
@juvix compile anoma $(juvix) -o $(nockma)

$(proved): $(nockma) $(config) $(message-file)
@juvix dev anoma -c $(config) prove $(nockma) -o $(proved) --arg 'bytes:$(message-file)'
$(proved): $(nockma) $(config) $(message-file) $(logic-proved)
juvix dev anoma -c $(config) prove $(nockma) -o $(proved) --arg 'bytes:$(logic-proved)' --arg 'bytes:$(message-file)'

$(kind-nockma): $(kind-juvix) $(anoma-build)
@juvix compile anoma $(kind-juvix) -o $(kind-nockma)

$(kind-proved): $(kind-nockma) $(config) $(logic-proved)
@juvix dev anoma -c $(config) prove $(kind-nockma) -o $(kind-proved) --arg 'bytes:$(logic-proved)'

$(kind-proved-cued): $(kind-proved)
@juvix dev nockma encode --cue --from bytes --to bytes < $(kind-proved) > $(kind-proved-cued)

$(kind-proved-cued-b64): $(kind-proved)
@juvix dev nockma encode --cue --from bytes --to base64 < $(kind-proved) > $(kind-proved-cued-b64)

$(filter-request): $(kind-proved-cued-b64)
jq -n --arg KIND $$(cat $(kind-proved-cued-b64)) \
'{node_info: {node_id: ""}, filters: [{kind: $$KIND}]}' \
> $(filter-request)

$(get-message-nockma): $(anoma-build) $(get-message-juvix)
@juvix compile anoma $(get-message-juvix) -o $(get-message-nockma)

$(logic-nockma): $(anoma-build) $(logic-juvix)
juvix compile anoma $(logic-juvix) -o $(logic-nockma)

$(logic-proved): $(logic-nockma) $(config)
juvix dev anoma -c $(config) prove $(logic-nockma) -o $(logic-proved)

.PHONY: $(unspent-resources)
$(unspent-resources): $(anoma-build) $(host) $(port)
@grpcurl -plaintext $$(cat $(host)):$$(cat $(port)) Anoma.Protobuf.IndexerService.ListUnspentResources | jq -r '.unspentResources[] // error("no messages exist")' > $(unspent-resources)
$(unspent-resources): $(anoma-build) $(host) $(port) $(filter-request)
@grpcurl -plaintext \
-d @ \
$$(cat $(host)):$$(cat $(port)) Anoma.Protobuf.BlockService.Filter \
< $(filter-request) \
| jq -r 'if has("resources") then .resources[] else empty end' \
> $(unspent-resources)

$(host): $(config)
@yq -r '.url' $(config) | tr -d '\n' > $(host)
Expand Down
4 changes: 2 additions & 2 deletions HelloWorld/tests/all-tests.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#!/usr/bin/env bash

-e
set -e

pushd message
./tests.sh
./test.sh
popd

echo "All HelloWorld tests passed"
20 changes: 19 additions & 1 deletion HelloWorld/web-app/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,21 @@ anoma-port = $(anoma-build-dir)/port

add-message-program = HelloWorld.nockma
get-message-program = GetMessage.nockma
logic-program = Logic.proved.nockma
kind = AppIdentity.cued.nockma

add-message-program-src = $(src)/$(add-message-program)
get-message-program-src = $(src)/$(get-message-program)
logic-program-src = $(src)/$(logic-program)
kind-src = $(src)/$(kind)

add-message-program-dst = $(dst)/$(add-message-program)
get-message-program-dst = $(dst)/$(get-message-program)
logic-program-dst = $(dst)/$(logic-program)
kind-dst = $(dst)/$(kind)

.PHONY: build
build: $(add-message-program-dst) $(get-message-program-dst)
build: $(add-message-program-dst) $(get-message-program-dst) $(logic-program-dst) $(kind-dst)

.PHONY: clean
clean:
Expand Down Expand Up @@ -74,8 +80,20 @@ $(add-message-program-dst): $(dst) $(add-message-program-src)
$(get-message-program-dst): $(dst) $(get-message-program-src)
cp $(get-message-program-src) $(get-message-program-dst)

$(logic-program-dst): $(dst) $(logic-program-src)
cp $(logic-program-src) $(logic-program-dst)

$(kind-dst): $(dst) $(kind-src)
cp $(kind-src) $(kind-dst)

$(add-message-program-src):
make -C $(app-path) compile-add-message

$(get-message-program-src):
make -C $(app-path) compile-get-message

$(logic-program-src):
make -C $(app-path) compile-logic

$(kind-src):
make -C $(app-path) compute-kind
8 changes: 6 additions & 2 deletions HelloWorld/web-app/src/index.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import { AnomaClient, fetchBinary, serialize, deserializeToString } from 'anoma-client';
import helloWorld from '../nockma/HelloWorld.nockma';
import getMessage from '../nockma/GetMessage.nockma'
import logic from '../nockma/Logic.proved.nockma'
import appIdentity from '../nockma/AppIdentity.cued.nockma'
import config from '../config.json'

const grpcServer = `http://${config.proxyHost}:${config.proxyPort}`
const anomaClient = new AnomaClient(grpcServer);

async function addMessage(message) {
const logicProgram = await fetchBinary(logic);
const helloWorldProgram = await fetchBinary(helloWorld);
const tx = await anomaClient.prove(helloWorldProgram, [message]);
const tx = await anomaClient.prove(helloWorldProgram, [logicProgram, message]);
return await anomaClient.addTransaction(tx);
}

async function getMessages() {
const unspent = await anomaClient.listUnspentResources();
const kind = await fetchBinary(appIdentity);
const unspent = await anomaClient.filterKind(kind);
if (unspent.length == 0) {
throw Error("There are no stored messages");
}
Expand Down
2 changes: 1 addition & 1 deletion HelloWorld/web-app/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ module.exports = {
},
],
},
mode: 'development'
mode: 'production'
};
16 changes: 14 additions & 2 deletions anoma-client/src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { IndexerServicePromiseClient, MempoolServicePromiseClient, NockServicePromiseClient } from './grpc-client/anoma_grpc_web_pb';
import { BlockServicePromiseClient, IndexerServicePromiseClient, MempoolServicePromiseClient, NockServicePromiseClient } from './grpc-client/anoma_grpc_web_pb';

import * as UnspentResources from './grpc-client/indexer/unspent_resources_pb.js';
import * as AddTransaction from './grpc-client/mempool/add_transaction_pb.js';
import * as Filtered from './grpc-client/indexer/blocks/filter_pb.js'
import * as Prove from './grpc-client/nock/prove_pb.js';
import { Input } from './grpc-client/nock/input_pb.js';
import serial from './nock-js/serial.js';
Expand All @@ -13,7 +14,8 @@ export async function fetchBinary(url) {
if (!response.ok) {
throw new Error(`Failed to fetch binary data: ${response.statusText}`);
}
return await response.arrayBuffer();
const buf = await response.arrayBuffer();
return new Uint8Array(buf);
}

export function serialize(x) {
Expand Down Expand Up @@ -42,6 +44,7 @@ export class AnomaClient {
this.indexerClient = new IndexerServicePromiseClient(grpcServer);
this.nockClient = new NockServicePromiseClient(grpcServer);
this.mempoolClient = new MempoolServicePromiseClient(grpcServer);
this.blockServiceClient = new BlockServicePromiseClient(grpcServer);
}

async listUnspentResources() {
Expand All @@ -50,6 +53,15 @@ export class AnomaClient {
return res.getUnspentResourcesList_asU8();
}

async filterKind(kind) {
const request = new Filtered.Request();
const filter = new Filtered.Filter();
filter.setKind(kind);
request.setFiltersList([filter]);
const response = await this.blockServiceClient.filter(request, {});
return response.getResourcesList_asU8();
}

async prove(program, args) {
const request = new Prove.Request();
request.setJammedProgram(program);
Expand Down

0 comments on commit 6132630

Please sign in to comment.