Closed barnjamin closed 3 years ago
Hi @barnjamin, could you explain what problem you're trying to solve by knowing the exact location of variables?
Also, I don't see how explicitly defining an intcblock
/bytecblock
would give you an exact location, since the placement of those statements would be very dependent on the expressions that appear before them.
Hi @jasonpaulos, my goal was to have a delegate signature check the receiver of an ASA to see that it is a contract account that was created with a specific template.
To do that I've got the sha256(teal assembly - variable bytes) compiled into that delegate sig and also check that the asset receiver address matches the sha512_256("Program"+ teal assembly).
To remove the template variable bytes I had to do some hacky stuff: https://github.com/barnjamin/rareaf/blob/main/contracts/platform-token.py#L79
What I'm trying to do is described more in detail here: https://github.com/barnjamin/rareaf/blob/main/contracts/platform.md
1) I'm not sure that this makes any sense to do 2) I'm not sure that this is even a good way to do this
As for exact placement, I think if you were to call those at the beginning of the teal script it should put them first?
I'd love to hear your thoughts on the idea but I'm sure this is not the arena for it. Still trying to understand the space so I'd appreciate any notes you have.
You could probably do something similar in terms of getting them added to the const block in the right order by just declaring a ScratchVar at the top a but the deduplication step will make it impossible (?) to do this.
@barnjamin thanks for explaining your problem more. This problem definitely makes sense, and I have some suggestions that may be useful.
Assuming you want a single fixed-length byte slice template variable for your contract, you could do the following:
goal
into a .teal.tok
file since there will be lines like byte TMPL_VALUE
. I suggest using the .teal.tmpl
file type to denote a TEAL program with some template values in it..teal.tmpl
from the previous step. This script can search for the template variable (it'll start with TMPL_
), replace all occurrences of it with a concrete placeholder value, then assemble the program using goal
into a .teal.tok
file. You can then search this file for the placeholder value to find the offset of the template variable in the final compiled contract..teal.tok
file and the offset where your template variable is, you can populate the template from within another PyTeal contract to calculate it's hash.Note that the hard part is step 2, specifically choosing a unique placeholder value. If you choose a byte string that appears somewhere else in your program, the assembler will deduplicate it and you'll end up accidentally modifying that other value too. Additionally, if the placeholder value is a sequence of bytes that happens to appear anywhere else in the .teal.tok
assembled program, your offset for the variable in the .teal.tok
program may be wrong.
The above steps can be extended to support multiple template variables too. It can also support int values if you use Btoi
and Itob
to convert them to/from bytes (Itob
always produces 8 bytes, so this doesn't violate the assumption of fixed-length byte slices). It's actually preferable to use byte slices to store ints instead of trying to encode/decode int values directly from the assembled .teal.tok
format because they are stored as varints, which would be very difficult to deal with in PyTeal.
@jasonpaulos thanks for the tips! I'll definitely use the TMPL_* vars in the teal template program and use a find/replace to populate them with real values in the final app. And the Btoi for ints instead of using ints directly makes more sense than comparing the value to determine number of bytes which felt bad to do.
The problem you mentioned about placeholders being unique is part of the problem I was hoping to address by setting values directly in the const blocks. If the compiler respects the values already set in the const block and doesn't de-duplicate them, I should be able to add TMPL* vars directly to the const block in the .teal
file and reference them later with just intc X
. Then swap the TMPL* values in the const block with the actual values and compile as normal.
That change would have to be implemented in the assembler and then possibly supported here so I'll just close this one and suggest it in the Teal 4.
Thanks again!
For a project I'm working on I'd like to know the exact byte location of given variables in the assembled teal for some static analysis.
Currently the intc/bytec blocks are created in the compilation processes and the variables are deduplicated which prevents the analysis I'd like to do.
Being able to call something like
IntConst(0, Int(500))
orByteConst(0, Byte("DEADBEEF"))
that create the intc/bytecblock lines would allow me to define the constants I'm interested in and know their precise location. The ByteConst would have to convert to binary.I think this will introduce another issue though because if those lines exist, the assembler will skip adding any other constants thinking that step has already been done.
The open PR here https://github.com/algorand/pyteal/pull/41 appears to make some changes to the bits that would be relevant so I haven't dug into the pyteal lib yet to see how I might go about doing this.