-
Notifications
You must be signed in to change notification settings - Fork 60
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
Bugfix allow account code change #784
Conversation
@@ -86,22 +86,19 @@ end | |||
|
|||
#! Sets an item in the account storage. Panics if the index is out of bounds. | |||
#! | |||
#! Stack: [index, V'] | |||
#! Stack: [index, V', 0, 0, 0] |
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 is because of #783
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 I mentioned in the comment for #783, I'm not sure I understood the motivation for this change. I think it was working as intended (e.g., the user would be able to do exec.account::set_item
and it would not insert any extra zeros into the stack. Or am I missing something?
@@ -98,7 +98,7 @@ impl fmt::Display for TransactionKernelError { | |||
) | |||
}, | |||
TransactionKernelError::UnknownAccountProcedure(proc_root) => { | |||
write!(f, "account procedure with root {proc_root} is not in the advice provider") | |||
write!(f, "Could not find account procedure with digest {proc_root} is in the advice provider, check the transactinon's account code") |
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 was confusing, it was unclear if it was the account procs hash, or the mast root of the procedure.
inputs: Vec<(Word, Vec<Felt>)>, | ||
targets: Vec<ScriptTarget>, | ||
}, | ||
} |
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 is a bit annoying, the tx script doesn't allow phantom calls, so the script must be compiled with an assembler which had the account loaded into it.
As the tests are currently setup, the assembler is kinda "hidden" inside the context. This structure is just to allow the test to pass script code that calls the account, and to have it compiled with the same assembler. Which then finally allows the tests to run against main.masm
instead of stand alone scripts, which is leading me to find issues like the one this PR is fixing.
|
||
pub fn set_tx_args(&mut self, tx_args: TransactionArgs) { | ||
self.tx_args = tx_args; | ||
} |
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 args are no longer created when instantiating the context, now it is created just before executing the transaction, this too is because of the tx script (because one needs the tx script object to create the tx arg one).
@@ -29,77 +29,56 @@ pub fn read_root_mem_value<H: Host>(process: &Process<H>, addr: u32) -> Word { | |||
process.get_mem_value(ContextId::root(), addr).unwrap() | |||
} | |||
|
|||
/// Given an slice of [Note]s, generates a procudere to initialize the VM's memory with the note's | |||
/// data. | |||
pub fn output_notes_data_procedure(notes: &[Note]) -> String { |
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 should allow one to simplify the context builder, and remove notes which are no longer needed, since the number of notes now can vary.
In the future it should also support notes with a variable number of assets.
} else if nonce.is_some() { | ||
return Err(AccountDeltaError::InconsistentNonceUpdate( | ||
"nonce updated for empty delta".to_string(), | ||
)); |
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 is the temporary bug fix.
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 think this check specifically has been discussed in the context of one of the pioneer's projects and a possibility was to remove it altogether (#765)
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.
even better :)
let new_acct_code_ast = | ||
ModuleAst::parse(source).map_err(AccountError::AccountCodeParsingError)?; | ||
AccountCode::new(new_acct_code_ast, &Assembler::default()) | ||
} |
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.
Just a convenience constructor. We never construct code directly from the AST, always from a string builder or str slice.
|
||
# acct proc 2 | ||
export.incr_nonce | ||
push.0 swap |
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 is done by account::incr_nonce
already.
4dbbb6b
to
8f6df50
Compare
#! Increments the account nonce by the provided value. | ||
#! | ||
#! Stack: [value] | ||
#! Output: [] | ||
#! | ||
#! - value is the value to increment the nonce by. value can be at most 2^32 - 1 otherwise this | ||
#! procedure panics. | ||
export.incr_nonce | ||
exec.account::incr_nonce | ||
# => [] | ||
end |
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.
Adding this procedure would lead to a security vulnerability: it will allow anyone to bypass an account's authentication mechanism. What is the motivation for adding it?
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 authentication mechanism is done in the kernel:
miden-base/miden-lib/asm/kernels/transaction/api.masm
Lines 131 to 132 in 89437d1
# authenticate that the procedure invocation originates from the account context | |
exec.authenticate_account_origin |
This is not skipping it (just like the other methods in this file)
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 mean the transaction authentication (e.g., where we require the user to provide a signature against an account's public key). Exposing this method publicly would allow anyone to bypass signature verification and update the account state at will.
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.
Ah, so the plan is to have the signature verification code calling the nonce increment? That makes sense, I was unaware of that flow.
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.
Moved it back to the test only.
#! Sets the code of the account the transaction is being executed against. This procedure can only | ||
#! executed on regular accounts with updatable code. Otherwise, this procedure fails. | ||
#! | ||
#! Stack: [CODE_ROOT] | ||
#! Output: [] | ||
#! | ||
#! - CODE_ROOT is the hash of the code to set. | ||
export.set_code | ||
exec.account::set_code | ||
# => [] | ||
end |
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.
Ability to update account code is not yet supported. Making it work properly is a relatively big task and I'm not sure we need to tackle it yet.
In either case though, adding it to the basic wallet interface is probably not the right approach (i.e., when we do make it work, it should probably be a part of a separate interface).
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.
Moved it back to the test only.
273d0c0
to
04e42d2
Compare
a704e72
to
15b07a3
Compare
@hackaugusto - could you rebase this from the latest |
This is needed to have the account's procedures available, because the tx_script is compiled without fantom calls.
Changes to the account code were forbidden in the Rust code, because the account delta nonce validation assumed the nonce would only change with changes to the vault or storage. Currently the account delta doesn't track changes to the account code, so as an intermediary solution this changes the check to allow code changes anytime. The correct solution would be to introduce the code change to the account delta too, and introduce that as another case in which the delta must change, and then forbid changes otherwise.
5f9641a
to
dcdc4c9
Compare
done |
The account delta check only allows the nonce to change if the storage or the vault changes. This is a problem, because it forbids changes to the account's code.
This relaxes the test, to fix the immediate issue, allowing the account code to change. In the future, however, the correct fix is to also track code changes in the account delta and include that in the nonce check.