-
Notifications
You must be signed in to change notification settings - Fork 11.6k
Basic module publishing and move calls from CLI. #133
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
Conversation
fastpay/src/client.rs
Outdated
path, | ||
gas_object_id, | ||
} => { | ||
let sender = decode_address(&account).expect("Failed to decode sender's address"); |
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.
Need to cleanup gas handling logic here
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 are right that the object_id and seq_num of orders make no sense any more.
fastpay/src/client.rs
Outdated
path: String, | ||
|
||
/// ID of the gas object for gas payment, in 20 bytes Hex string | ||
gas_object_id: 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.
Do we need to provide both the gas_object and the account? The gas object presumably has an owner, whose account is assumed to be used no?
let objects_ids = client_state.object_ids(); | ||
// Try to sync. | ||
// TODO: figure out optimal tuning for high probability of getting full data back | ||
for _ in 0..(1 + committee_config.authorities.len() / 3) { |
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.
To keep it simple right now : Just ask all of them?
fastpay_core/src/client.rs
Outdated
gas_payment: ObjectRef, | ||
module: Vec<u8>, | ||
) -> Result<CertifiedOrder, anyhow::Error> { | ||
let module_bytes = vec![module]; |
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.
Is this not already a vec? Do we need a vec<vec> here?
fastpay_core/src/client.rs
Outdated
let new_sent_certificates = self | ||
.communicate_transfers( | ||
self.address, | ||
*order.object_id(), |
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 place where we should not have object_id
fastpay_core/src/client.rs
Outdated
if with_confirmation { | ||
self.communicate_transfers( | ||
self.address, | ||
*order.object_id(), |
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.
Here as well this object_id
makes no sense now.
fastpay_core/src/client.rs
Outdated
self.address, | ||
*order.object_id(), | ||
self.sent_certificates.clone(), | ||
CommunicateAction::SynchronizeNextSequenceNumber( |
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.
Are these seq numbers per object, otherwise they are also legacy.
Box::pin(self.publish( | ||
( | ||
gas_payment, | ||
self.next_sequence_number(gas_payment), |
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.
Should this be the next, or the current sequence number?
Somehow this option did not show up in my autocomplete so I thought you made a typo Co-authored-by: Sam Blackshear <sam@mystenlabs.com>
..Default::default() | ||
}; | ||
let package = build_cfg | ||
.compile_package(&path, &mut Vec::new()) |
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 will compile just fine, but unfortunately the compiled modules will fail to link against anything that's already published on-chain. That is, the package might have something like:
module MyPackage::MyModule {
use FastX::ID;
}
. Compiling this code will produce a module handle 0x2::ID
, but the on-chain handle for that type is 0x3C2B307C3239F61643AF5E9A09D7D0C9::ID
We need to do something like https://github.com/MystenLabs/fastnft/blob/main/fastx_programmability/adapter/src/adapter.rs#L186, but that rewrites handles referring to modules already published on-chain.
CC @lxfind to double-check that this makes sense.
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.
@sblackshear We do it here during module publishing in the adapter: https://github.com/MystenLabs/fastnft/blob/main/fastx_programmability/adapter/src/adapter.rs#L156
right?
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 ok the FastX framework is special in the sense that it has a built-in address which is 0x2 in the move.toml, but with a different address on-chain. So for any modules being published, we first need to remap all of 0x2 to the right on-chain address. But this is specific to 0x2, right? For any new addresses, they would be fine because devs don't define their own address?
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.
Yes, I think this should be specific to 0x2 in the short term.
In the longer term, there's a thorny question of how to write a package P1
such that another user-defined package P2
can easily depend on it. The two options seem to be
P1
follows the FastX framework style and writes every module asmodule P1::MyModule
. We'll then need to have the client understand and/or discover how to rewrite eachP1
as well.P1
directly uses theObjectID
's of its modules -- e.g.module MyModule::MyModule
+ addMyModule = 0x2fe5ca...
in Move.toml (and we could also refactor the framework to do this if desired). The problem with this approach is it's somewhat annoying as a dev--you will have to declare a new Move.toml symbolic address for every module and you won't be able to update it to its final value until you've actually published the package. Maybe we could have the client tooling fill in the symbolic address for you in the package manifest before compiling/publishing, though.
I have a slight preference for (1) because I think it will be easier to use Move packages from elsewhere that don't follow the "one address per module" convention (e.g., the Move stdlib!) but needs more thought/discussion...
} | ||
|
||
fn find_owner_by_object_cache( | ||
account_config: &mut AccountsConfig, |
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.
account_config: &mut AccountsConfig, | |
account_config: &AccountsConfig, |
gas_budget, | ||
} => { | ||
// Find owner of acc | ||
let owner = find_owner_by_object_cache(&mut accounts_config, gas_object_id) |
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 seems ok for now, but a TODO to add a designated owner
field to AccountConfig
might be good.
|
||
// TODO: this somehow turns into a Vec<Vec<u8>>, how? | ||
/// Pure args | ||
//pure_args: 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.
Try
#[structopt(long = "args", parse(try_from_str = parser::parse_transaction_argument))]
args: Vec<TransactionArgument>,
here. Then, you can use https://github.com/diem/diem/blob/main/language/move-core/types/src/transaction_argument.rs#L75 to turn it into a Vec<Vec<u8>>
|
||
// // TODO: object args from | ||
// /// Pure args | ||
// object_args: 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.
// object_args: String, |
for acc in account_config.accounts() { | ||
if acc.object_ids.contains_key(&object_id) { | ||
return Some(acc.address); | ||
} | ||
} |
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.
Consider
for acc in account_config.accounts() if acc.object_ids.contains_key(&object_id) {
return Some(acc.address);
}
or
account_config.accounts().find_map(|acc| {
if acc.object_ids.contains_key(&object_id)) {
Some(acc.address);
} else {
None
}
}
// Fetch the obj ref | ||
let obj_info_req = ObjectInfoRequest { | ||
object_id: gas_object_id, | ||
request_sequence_number: None, | ||
request_received_transfers_excluding_first_nth: None, | ||
}; | ||
|
||
let gas_obj_info = client_state.get_object_info(obj_info_req).await.unwrap(); | ||
object_args_refs.push(gas_obj_info.object.to_object_reference()); |
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.
Since there is no loop index, those values are rebuilt identically on every iteration. Is that really what you want?
.clone() | ||
.unwrap() |
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.
In general, you want to unwrap before you clone, or use cloned. Not that you need to clone here (see the into_iter comment).
.effects | ||
.mutated | ||
{ | ||
self.object_ids.insert(obj_id, seq_no); |
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.
... and more generally, this is the line where I would expect to see the clone if there needed to be one. Not that you need to clone here (see the into_iter comment).
@@ -579,6 +705,55 @@ where | |||
Ok(()) | |||
} | |||
|
|||
fn update_objects_from_order_info(&mut self, order_info_resp: OrderInfoResponse) { | |||
// TODO: use the digest also | |||
for (obj_id, seq_no, _) in order_info_resp |
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 can iterate on values directly with into_iter
.
@@ -579,6 +705,55 @@ where | |||
Ok(()) | |||
} | |||
|
|||
fn update_objects_from_order_info(&mut self, order_info_resp: OrderInfoResponse) { |
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.
In this function, are order_info_resp.signed_effects.unwrap()
instances really representative of an irrecoverable error that should crash the node?
self.update_certificates(vec![new_certificate.clone()])?; | ||
|
||
// Confirmation | ||
let order_info = self | ||
.communicate_confirmation_order(&new_certificate) | ||
.await?; |
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 pattern is repeated multiple time: note that if it makes sense to communicate the new certificate before the local update, you can avoid a clone (if it doesn't, it's not a big deal).
Handling Calls separately while publish system is being worked out |
Adding support for Move calls and module publishing from user CLI
Example publish:
TODO: