Define transport envelope standard #1

Closed
opened 2024-11-20 22:47:14 +00:00 by lrvick · 4 comments
Owner

When sending an object from online icepick to offline icepick, an envelope is required to claify the chain, operation type, to address, and from address, so the correct curve, derivation path, etc are used.

Suggested keys: to, from, chain, payload

When sending an object from online icepick to offline icepick, an envelope is required to claify the chain, operation type, to address, and from address, so the correct curve, derivation path, etc are used. Suggested keys: to, from, chain, payload
lrvick added this to the Custody Framework project 2024-11-21 04:12:59 +00:00
Owner

Chain, curve, and derivation path should all be verified out of band (probably within the keyfork-derive-path-data crate) so malicious module code can't say "hey I'm actually bitcoin, give me the xprv for m/44'/0'". Then, when Icepick sees "hey I should register support for the SOL module", it can use something like:

const sol_path_prefix = keyfork_derive_path_data::cryptocurrency_prefixes().get("SOL").unwrap();

Or...

const sol_path_prefix = keyfork_derive_path_data::cryptocurrency_prefix("SOL");

Both can be const since they're "just" data definitions. Second one implicitly panics.

Chain, curve, and derivation path should all be verified out of band (probably within the `keyfork-derive-path-data` crate) so malicious module code can't say "hey I'm actually bitcoin, give me the xprv for `m/44'/0'`". Then, when Icepick sees "hey I should register support for the SOL module", it can use something like: ```rust const sol_path_prefix = keyfork_derive_path_data::cryptocurrency_prefixes().get("SOL").unwrap(); ``` Or... ```rust const sol_path_prefix = keyfork_derive_path_data::cryptocurrency_prefix("SOL"); ``` Both can be const since they're "just" data definitions. Second one implicitly panics.
Owner

Currently I've defined the envelope as:

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "kebab-case")]
pub struct Request {
    // NOTE: Can't use the proper XPrv type from Keyfork because Solana's a big stinky
    // and adds in its own derivation constructs that cause type conflicts.
    derived_keys: Option<Vec<[u8; 32]>>,

    // NOTE: This is an opaque type that can be deserialized inside an Operation
    blob: Option<serde_json::Value>,

    #[serde(flatten)]
    operation: Operation,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(tag = "operation", content = "values", rename_all = "kebab-case")]
pub enum Operation {
    Transfer(Transfer),
    Sign(Sign),
}

This defines the inbound format as:

{
    "derived_keys": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
    "blob": {
        "data": "This is just the JSON value stored in the 'blob' from the previous command, piped into this command."
    },
    "operation": "sign",
    "values": {}
}

Note that we can't define a to, a from, or even an amount since communicating with the module on sign means we have zero additional inputs. Just the provided derived key and the previous blob.

Currently I've defined the envelope as: ```rust #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "kebab-case")] pub struct Request { // NOTE: Can't use the proper XPrv type from Keyfork because Solana's a big stinky // and adds in its own derivation constructs that cause type conflicts. derived_keys: Option<Vec<[u8; 32]>>, // NOTE: This is an opaque type that can be deserialized inside an Operation blob: Option<serde_json::Value>, #[serde(flatten)] operation: Operation, } #[derive(Serialize, Deserialize, Debug)] #[serde(tag = "operation", content = "values", rename_all = "kebab-case")] pub enum Operation { Transfer(Transfer), Sign(Sign), } ``` This defines the inbound format as: ```json { "derived_keys": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], "blob": { "data": "This is just the JSON value stored in the 'blob' from the previous command, piped into this command." }, "operation": "sign", "values": {} } ``` Note that we can't define a `to`, a `from`, or even an `amount` since communicating with the module on `sign` means we have _zero_ additional inputs. Just the provided derived key and the previous blob.
Owner

add a config file for this perhaps so i don't have to hardcode everything within icepick thnak u anton

add a config file for this perhaps so i don't have to hardcode everything within icepick thnak u anton
ryan added a new dependency 2024-11-26 16:57:38 +00:00
ryan self-assigned this 2024-12-05 19:46:51 +00:00
Owner

This is for the most part done and will probably be automated w/ the inclusion of #[derive(icepick_module::Interface)] to allow importing derived keys, blobs, operation, and values, as well as exporting blobs and derived accounts.

This is for the most part done and will probably be automated w/ the inclusion of `#[derive(icepick_module::Interface)]` to allow importing derived keys, blobs, operation, and values, as well as exporting blobs and derived accounts.
ryan closed this issue 2024-12-12 20:32:15 +00:00
ryan added this to the Icepick v0.1.0 milestone 2024-12-12 20:32:23 +00:00
Sign in to join this conversation.
No Label
No Milestone
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Blocks
Reference: public/icepick#1
No description provided.