Skip to content

Commit

Permalink
Paych actor: Drop account req, use AuthenticateMessage to verify sigs (
Browse files Browse the repository at this point in the history
…#824)

* Paych actor: Drop account req, use AuthenticateMessage to verify sigs

* Address review

* Address review
  • Loading branch information
arajasek committed Dec 5, 2022
1 parent ece6524 commit 370bfa2
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 172 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions actors/paych/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ crate-type = ["cdylib", "lib"]

[dependencies]
fil_actors_runtime = { version = "10.0.0-alpha.1", path = "../../runtime" }
frc42_dispatch = "1.0.0"
fvm_shared = { version = "2.0.0-alpha.2", default-features = false }
num-traits = "0.2.14"
num-derive = "0.3.3"
Expand Down
17 changes: 17 additions & 0 deletions actors/paych/src/ext.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use fvm_ipld_encoding::serde_bytes;
use fvm_ipld_encoding::tuple::*;

pub mod account {
use super::*;

pub const AUTHENTICATE_MESSAGE_METHOD: u64 =
frc42_dispatch::method_hash!("AuthenticateMessage");

#[derive(Serialize_tuple, Deserialize_tuple)]
pub struct AuthenticateMessageParams {
#[serde(with = "serde_bytes")]
pub signature: Vec<u8>,
#[serde(with = "serde_bytes")]
pub message: Vec<u8>,
}
}
60 changes: 33 additions & 27 deletions actors/paych/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
use fil_actors_runtime::runtime::builtins::Type;
use fil_actors_runtime::runtime::{ActorCode, Runtime};
use fil_actors_runtime::{
actor_error, cbor, resolve_to_actor_id, restrict_internal_api, ActorDowncast, ActorError, Array,
actor_error, cbor, resolve_to_actor_id, restrict_internal_api, ActorDowncast, ActorError,
Array, AsActorError,
};
use fvm_ipld_blockstore::Blockstore;
use fvm_ipld_encoding::RawBytes;
Expand All @@ -22,6 +23,7 @@ pub use self::types::*;
#[cfg(feature = "fil-actor")]
fil_actors_runtime::wasm_trampoline!(Actor);

pub mod ext;
mod state;
pub mod testing;
mod types;
Expand All @@ -42,17 +44,24 @@ pub const ERR_CHANNEL_STATE_UPDATE_AFTER_SETTLED: ExitCode = ExitCode::new(32);

/// Payment Channel actor
pub struct Actor;

impl Actor {
/// Constructor for Payment channel actor
pub fn constructor(rt: &mut impl Runtime, params: ConstructorParams) -> Result<(), ActorError> {
// Only InitActor can create a payment channel actor. It creates the actor on
// behalf of the payer/payee.
rt.validate_immediate_caller_type(std::iter::once(&Type::Init))?;

// Check both parties are capable of signing vouchers
let to = Self::resolve_account(rt, &params.to)?;
// Resolve both parties, confirming they exist in the state tree.
let to = Self::resolve_address(rt, &params.to)
.with_context_code(ExitCode::USR_ILLEGAL_ARGUMENT, || {
format!("to address not found {}", params.to)
})?;

let from = Self::resolve_account(rt, &params.from)?;
let from = Self::resolve_address(rt, &params.from)
.with_context_code(ExitCode::USR_ILLEGAL_ARGUMENT, || {
format!("to address not found {}", params.to)
})?;

let empty_arr_cid =
Array::<(), _>::new_with_bit_width(rt.store(), LANE_STATES_AMT_BITWIDTH)
Expand All @@ -65,26 +74,14 @@ impl Actor {
Ok(())
}

/// Resolves an address to a canonical ID address and requires it to address an account actor.
fn resolve_account(rt: &mut impl Runtime, raw: &Address) -> Result<Address, ActorError> {
/// Resolves an address to a canonical ID address and confirms it exists in the state tree.
fn resolve_address(rt: &mut impl Runtime, raw: &Address) -> Result<Address, ActorError> {
let resolved = resolve_to_actor_id(rt, raw)?;

let code_cid = rt
.get_actor_code_cid(&resolved)
.ok_or_else(|| actor_error!(illegal_argument, "no code for address {}", resolved))?;

let typ = rt.resolve_builtin_actor_type(&code_cid);
if typ != Some(Type::Account) {
Err(actor_error!(
forbidden,
"actor {} must be an account, was {} ({:?})",
raw,
code_cid,
typ
))
} else {
Ok(Address::new_id(resolved))
}
// so long as we can find code for this, return `resolved`
rt.get_actor_code_cid(&resolved)
.map(|_| Address::new_id(resolved))
.ok_or_else(|| actor_error!(illegal_argument, "no code for address {}", resolved))
}

pub fn update_channel_state(
Expand All @@ -98,10 +95,11 @@ impl Actor {
let sv = params.sv;

// Pull signature from signed voucher
let sig = sv
let sig = &sv
.signature
.as_ref()
.ok_or_else(|| actor_error!(illegal_argument, "voucher has no signature"))?;
.ok_or_else(|| actor_error!(illegal_argument, "voucher has no signature"))?
.bytes;

if st.settling_at != 0 && rt.curr_epoch() >= st.settling_at {
return Err(ActorError::unchecked(
Expand All @@ -120,9 +118,17 @@ impl Actor {
})?;

// Validate signature
rt.verify_signature(sig, &signer, &sv_bz).map_err(|e| {
e.downcast_default(ExitCode::USR_ILLEGAL_ARGUMENT, "voucher signature invalid")
})?;

rt.send(
&signer,
ext::account::AUTHENTICATE_MESSAGE_METHOD,
RawBytes::serialize(ext::account::AuthenticateMessageParams {
signature: sig.to_vec(),
message: sv_bz,
})?,
TokenAmount::zero(),
)
.map_err(|e| e.wrap("voucher sig authentication failed"))?;

let pch_addr = rt.message().receiver();
let svpch_id = rt.resolve_address(&sv.channel_addr).ok_or_else(|| {
Expand Down
2 changes: 2 additions & 0 deletions actors/paych/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,7 @@ pub struct Merge {
}

impl Cbor for State {}

impl Cbor for LaneState {}

impl Cbor for Merge {}
Loading

0 comments on commit 370bfa2

Please sign in to comment.