glow
glow copied to clipboard
Fix compiler: Consensus code generation fails for following contract
In GitLab by @kwanzknoel on May 25, 2021, 17:41
#lang glow
@interaction([Sender, Recipient])
let transfer = (price : Nat) => {
deposit! Sender -> price;
@Sender let depositStatus = "Sender: Depositing funds";
publish! Sender -> depositStatus;
// Receiver is now the active participant
@Recipient let withdrawStatus = "Receiver: Withdrawing funds";
publish! Recipient -> withdrawStatus;
withdraw! Recipient <- price;
};
Trace:
> ./glow start-interaction --backtrace
Connecting to the Cardano EVM Devnet at https://rpc-evm.portal.dev.cardano.org/ ...
Choose application:
1) buy_sig
2) coin_flip
3) hello
4) rps_simple
5) simple-funds-transfer.solution
6) tmp
7) transfer
Enter number
>
Choose your identity:
1) alice - 0x4c371dA6E338F19B77BC78498DaFcFB05E8bd2Ac
2) bob - 0x0C7A123580a2A6E40b053b2dE913fd0e2B8b91e9
3) charles - 0x47312084A1026E2B5ae7E3A7ef6f328421740961
Enter number
>
Choose your role:
1) Recipient
2) Sender
Enter number
>
Assign roles
Select address for Recipient:
1) alice - 0x4c371dA6E338F19B77BC78498DaFcFB05E8bd2Ac
2) bob - 0x0C7A123580a2A6E40b053b2dE913fd0e2B8b91e9
3) charles - 0x47312084A1026E2B5ae7E3A7ef6f328421740961
Enter number
>
Define parameters
Enter price
>
Max initial block [ Current block number is 127588 ]
>
One line command for other participants to generate the same agreement:
glow start-interaction --agreement '{"glow-version":"Glow v0.1.0-128-g062f6c1","interaction":"transfer#transfer","participants":{"Recipient":"0x0C7A123580a2A6E40b053b2dE913fd0e2B8b91e9","Sender":"0x4c371dA6E338F19B77BC78498DaFcFB05E8bd2Ac"},"parameters":{"price":"0xf4240"},"reference":{},"options":{"blockchain":"Cardano EVM Devnet","timeoutInBlocks":"0x3e8","maxInitialBlock":"0x1f400"},"code-digest":"0x72987b797fae208ec75abe4b5d6ea863edf6d9a2e543174d5a08412eeb2a7741"}'
Glow v0.1.0-128-g062f6c1 on Gerbil-ethereum v0.0-260-gb151403, Gerbil-persist v0.0-19-g75d4c45, Gerbil-crypto ef0ef55, Gerbil-poo 5b2290f, Gerbil-utils v0.0-316-g3c748ed, Gerbil v0.16-178-g17fbcb95, Gambit v4.9.3-1389-g55b21ed9
In thread primordial:
0 std/misc/hash#hash-ensure-ref (_default34947_)
_table34945_ == '#<table #81>
_key34946_ == 'n
1 std/misc/hash#hash-ensure-ref (_default34947_)
_table34945_ == '#<table #81>
_key34946_ == '.length-in-bytes
2 mukn/glow/runtime/consensus-code-generator#add-local-variable-to-frame
3 mukn/glow/runtime/consensus-code-generator#compile-consensus-statement
4 std/srfi/1#really-append-map (_f2293_ _elt2312_)
_appender2292_ == append
_f2293_ == '#<procedure #82>
_rest2313_ == '((@debug-label dlb3))
5 std/srfi/1#really-append-map (_recur2310_ (car _rest2313_) (cdr _re...
_appender2292_ == append
_vals2315_ == '()
6 mukn/glow/runtime/consensus-code-generator#generate-consensus-code-block
7 std/srfi/1#really-append-map (_f2293_ _elt2312_)
_appender2292_ == append
_f2293_ == '#<procedure #83>
_rest2313_ == '((cp0 . #84 #;{participant: … statements: … exit: #f}))
8 mukn/glow/runtime/consensus-code-generator#&define-medium-functions
9 consensus-code-generator__0#
10 ##dynamic-env-bind
11 participant-runtime__0#
12 mukn/glow/runtime/reify-contract-parameters#run
13 mukn/glow/cli/interaction#start-interaction__%
14 ##dynamic-env-bind
15 ##call-with-values
16 clan/exit#call-print-exit
17 ##dynamic-env-bind
18 ##start-main
19 ##kernel-handlers
*** ERROR IN std/misc/hash#hash-ensure-ref -- This object was raised: #<NoApplicableMethod #85 self: #86 #;Bytes slot: n>
In GitLab by @fahree on May 26, 2021, 21:37
My guess is that the string contents get compiled to some variant of a Bytes
type that thinks it's fixed-size, even though it's actually variable-sized... which we don't support yet. Sigh.
In GitLab by @kwanzknoel on May 27, 2021, 15:58
assigned to @kwanzknoel
In GitLab by @kwanzknoel on Jun 2, 2021, 03:06
I have done a bit more digging:
The Bytes
type is variably sized.
Within consensus-code-gen
we call compile-consensus-statement
.
This calls param-length
which attempts to extract the static length of the value from the type.
In the case of Bytes
this is not statically available, and fails.
For Bytes
this should not have to be done. Reason being when encoded, the first Stack Address contains a UInt16
which provides us with the size of the Bytes
during runtime.
I shall look into it further to see how we can support variable-sized primitive data-types.
EDIT: Following #80, we can make Bytes
constant size, by just supplying the length of the EVM memory offset. We then use the type descriptor of imm/non-imm to discriminate marshalling / unmarshalling.
In GitLab by @kwanzknoel on Jun 2, 2021, 03:07
Another possible (simpler?) workaround is to do what etherjs does and just have fixed length strings, padded with null bytes.
https://docs.ethers.io/v4/api-utils.html#bytes32-strings
In GitLab by @kwanzknoel on Jun 2, 2021, 03:30
marked this issue as related to #194
In GitLab by @kwanzknoel on Jun 2, 2021, 03:55
removed the relation with #194
In GitLab by @kwanzknoel on Jun 2, 2021, 03:55
marked this issue as related to #80
In GitLab by @fahree on Jun 3, 2021, 23:37
- For bytes constants, we could use fixed-size still, just with a type that looks for the size in the constant itself.
- For bytes variables with a constant size, we could also use a type that looks for size in a "constant expression" that is known to reduce to a constant before runtime.
- For bytes variables with a runtime-variable size, we will need support for variable-size objects, and a heap.
In GitLab by @fahree on Jun 3, 2021, 23:46
The more I think about it, the more I believe we should first implement the unoptimized general case as an interpreter, then go for optimizations and compilation.
In GitLab by @alex413 on Jun 22, 2021, 03:32
Is this currently blocking anything?
In GitLab by @kwanzknoel on Jun 24, 2021, 02:01
Nope.