-
Notifications
You must be signed in to change notification settings - Fork 220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow seeds to be passed into functions as string[] or string[][] #1547
Conversation
import {AccountMeta} from 'solana';
contract pda {
address constant tokenProgramId = address"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
address constant SYSVAR_RENT_PUBKEY = address"SysvarRent111111111111111111111111111111111";
function test_bytes4(string[][] seeds) public {
bytes instr = new bytes(1);
instr[0] = 0x95;
AccountMeta[1] metas = [
AccountMeta({pubkey: SYSVAR_RENT_PUBKEY, is_writable: false, is_signer: false})
];
tokenProgramId.call{seeds: seeds, accounts: metas}(instr);
}
} Is this expected?
|
import {AccountMeta} from 'solana';
contract pda {
address constant tokenProgramId = address"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
address constant SYSVAR_RENT_PUBKEY = address"SysvarRent111111111111111111111111111111111";
function test(bytes[] dyn, address[] addr, bytes5[] b5) public {
bytes instr = new bytes(1);
instr[0] = 0x95;
AccountMeta[1] metas = [
AccountMeta({pubkey: SYSVAR_RENT_PUBKEY, is_writable: false, is_signer: false})
];
bytes3 foo = "foo";
string foo2 = "123456";
tokenProgramId.call{seeds: [ dyn, addr, b5, [foo, foo2] ], accounts: metas}(instr);
}
} Is this expected (part 2)?
|
Strings should be allowed, shouldn't they? import {AccountMeta} from 'solana';
contract pda {
address constant tokenProgramId = address"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
address constant SYSVAR_RENT_PUBKEY = address"SysvarRent111111111111111111111111111111111";
function test(bytes[] dyn, string[] addr, bytes5[] b5) public {
bytes instr = new bytes(1);
instr[0] = 0x95;
AccountMeta[1] metas = [
AccountMeta({pubkey: SYSVAR_RENT_PUBKEY, is_writable: false, is_signer: false})
];
bytes3 foo = "foo";
bytes6 foo2 = "123456";
tokenProgramId.call{seeds: [ dyn, addr, b5, [foo, foo2] ], accounts: metas}(instr);
}
}
|
Type |
let dest = call!("__malloc", &[i32_const!(bytes_length).into()]) | ||
.try_as_basic_value() | ||
.left() | ||
.unwrap() | ||
.into_pointer_value(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You've already allocated memory here to save the bytes value. It is necessary to allocate again?
You can swap endianness in place and return a pointer to the stack allocated memory.
[1, 2, 3, 4, 5]
^ ^
|-----------| ==> swap(1, 5)
[5, 2, 3, 4, 1]
^ ^
|-----| ==> swap(2, 4)
[5, 4, 3, 2, 1]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other allocation is on the stack and that is a single allocation. This malloc allocation is per-slice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You do not need to allocate space in the stack and in the heap. You can allocate the memory in one place (heap or stack), store the integer there, change the endianness in place and return the pointer to that memory region.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be something for another PR. We do all our endian-ness swaps like this.
In fact, I think bytesN
should be represented by a byte array and then all these swaps would go away.
import {AccountMeta} from 'solana';
contract pda {
address constant tokenProgramId = address"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
address constant SYSVAR_RENT_PUBKEY = address"SysvarRent111111111111111111111111111111111";
function test(bytes[] dyn, address[] addr, bytes5[] b5, string f) public {
bytes instr = new bytes(1);
instr[0] = 0x95;
AccountMeta[1] metas = [
AccountMeta({pubkey: SYSVAR_RENT_PUBKEY, is_writable: false, is_signer: false})
];
bytes3 foo = "foo";
tokenProgramId.call{seeds: [ dyn, addr, b5, [f] ], accounts: metas}(instr);
}
} Is this correct?
|
I also tested the following example, but I am not confident it is going to be a common construct, so perhaps we should not worry about it. import {AccountMeta} from 'solana';
contract pda {
address constant tokenProgramId = address"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
address constant SYSVAR_RENT_PUBKEY = address"SysvarRent111111111111111111111111111111111";
function test_bytes(bytes[][] seeds) public {
bytes instr = new bytes(1);
instr[0] = 0x95;
AccountMeta[1] metas = [
AccountMeta({pubkey: SYSVAR_RENT_PUBKEY, is_writable: false, is_signer: false})
];
tokenProgramId.call{seeds: [seeds[0], seeds[1]], accounts: metas}(instr);
}
}
|
c5e81da
to
2958604
Compare
@LucasSte I've added the two cases you found as a test cases |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM overall, just some cosmetics
src/emit/expression.rs
Outdated
@@ -2120,3 +2122,227 @@ fn runtime_cast<'a>( | |||
_ => unreachable!(), | |||
} | |||
} | |||
|
|||
/// Emit expression into a slice |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: Superfluous. A more useful comment could for example say when this is needed or explain the return type (which I'd guess is a pointer to the slice and the length of the slice)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, that comment is terrible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed in the standup, it would be great to have those SAFETY
comments, explaining our thoughts around why all those arguments to the LLVM GEP builder are correct. But it's not only in this place, I'll leave it up to you.
Fixes hyperledger-solang#1433 Signed-off-by: Sean Young <[email protected]>
Signed-off-by: Sean Young <[email protected]>
Signed-off-by: Sean Young <[email protected]>
Signed-off-by: Sean Young <[email protected]>
Signed-off-by: Sean Young <[email protected]>
Signed-off-by: Sean Young <[email protected]>
Signed-off-by: Sean Young <[email protected]>
Signed-off-by: Sean Young <[email protected]>
Signed-off-by: Sean Young <[email protected]>
Signed-off-by: Sean Young <[email protected]>
Signed-off-by: Sean Young <[email protected]>
Signed-off-by: Sean Young <[email protected]>
Signed-off-by: Sean Young <[email protected]>
Signed-off-by: Sean Young <[email protected]>
Signed-off-by: Sean Young <[email protected]>
Signed-off-by: Sean Young <[email protected]>
What do you think of the SAFETY comments I've just added? |
Great, this is exactly what I meant, thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested it locally and couldn't find any problem. Codewise, everything looks good. I have only one last question.
Should there be an integration test for this feature?
Co-authored-by: Lucas Steuernagel <[email protected]> Signed-off-by: Sean Young <[email protected]>
Signed-off-by: Sean Young <[email protected]>
I've added a simple test. This will need re-writing for your branch. There is also a fix for the "blockhash not found" issue (at least it fixes it locally) |
This fixes this Solidity and similar constructs.
Fixes #1433