mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 10:31:04 +00:00
contracts: add sr25519_verify (#13724)
* wip * fix * wip * fix lint * rm fixture fix * missing comment * fix lint * add comment to the wsm file * fix comment * Apply suggestions from code review Co-authored-by: Sasha Gryaznov <hi@agryaznov.com> * wip * wip weights * wip weights * PR comment: test with return code * wip * PR review add mock test * remove * lint * Update frame/contracts/fixtures/sr25519_verify.wat * fix comments * Update frame/contracts/src/benchmarking/mod.rs * Update frame/contracts/src/wasm/runtime.rs * Update frame/contracts/fixtures/sr25519_verify.wat * Update frame/contracts/src/benchmarking/mod.rs * fix lint * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * Update frame/contracts/src/wasm/runtime.rs Co-authored-by: Alexander Theißen <alex.theissen@me.com> * PR: review use unstable + remove arbitrary index 4 * Add benchmark for calculating overhead of calling sr25519_verify * fix message length encoding * fix weights * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * Apply suggestions from code review * Update frame/contracts/src/wasm/runtime.rs * Update frame/contracts/src/wasm/runtime.rs * Update frame/contracts/src/benchmarking/mod.rs * Update frame/contracts/src/benchmarking/mod.rs * Update frame/contracts/src/schedule.rs Co-authored-by: Sasha Gryaznov <hi@agryaznov.com> * Update frame/contracts/src/schedule.rs Co-authored-by: Sasha Gryaznov <hi@agryaznov.com> * Update frame/contracts/src/wasm/runtime.rs * Update frame/contracts/src/wasm/runtime.rs Co-authored-by: Sasha Gryaznov <hi@agryaznov.com> * PR review --------- Co-authored-by: Sasha Gryaznov <hi@agryaznov.com> Co-authored-by: command-bot <> Co-authored-by: Alexander Theißen <alex.theissen@me.com>
This commit is contained in:
@@ -434,6 +434,7 @@ mod tests {
|
||||
gas_meter: GasMeter<Test>,
|
||||
debug_buffer: Vec<u8>,
|
||||
ecdsa_recover: RefCell<Vec<([u8; 65], [u8; 32])>>,
|
||||
sr25519_verify: RefCell<Vec<([u8; 64], Vec<u8>, [u8; 32])>>,
|
||||
code_hashes: Vec<CodeHash<Test>>,
|
||||
}
|
||||
|
||||
@@ -458,6 +459,7 @@ mod tests {
|
||||
gas_meter: GasMeter::new(Weight::from_parts(10_000_000_000, 10 * 1024 * 1024)),
|
||||
debug_buffer: Default::default(),
|
||||
ecdsa_recover: Default::default(),
|
||||
sr25519_verify: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -612,6 +614,10 @@ mod tests {
|
||||
self.ecdsa_recover.borrow_mut().push((*signature, *message_hash));
|
||||
Ok([3; 33])
|
||||
}
|
||||
fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool {
|
||||
self.sr25519_verify.borrow_mut().push((*signature, message.to_vec(), *pub_key));
|
||||
true
|
||||
}
|
||||
fn contract_info(&mut self) -> &mut crate::ContractInfo<Self::T> {
|
||||
unimplemented!()
|
||||
}
|
||||
@@ -1319,6 +1325,49 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contract_sr25519() {
|
||||
const CODE_SR25519: &str = r#"
|
||||
(module
|
||||
(import "seal0" "sr25519_verify" (func $sr25519_verify (param i32 i32 i32 i32) (result i32)))
|
||||
(import "env" "memory" (memory 1 1))
|
||||
(func (export "call")
|
||||
(drop
|
||||
(call $sr25519_verify
|
||||
(i32.const 0) ;; Pointer to signature.
|
||||
(i32.const 64) ;; Pointer to public key.
|
||||
(i32.const 16) ;; message length.
|
||||
(i32.const 96) ;; Pointer to message.
|
||||
)
|
||||
)
|
||||
)
|
||||
(func (export "deploy"))
|
||||
|
||||
;; Signature (64 bytes)
|
||||
(data (i32.const 0)
|
||||
"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
|
||||
"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
|
||||
"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
|
||||
"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
|
||||
)
|
||||
|
||||
;; public key (32 bytes)
|
||||
(data (i32.const 64)
|
||||
"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
|
||||
"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
|
||||
)
|
||||
|
||||
;; message. (16 bytes)
|
||||
(data (i32.const 96)
|
||||
"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
|
||||
)
|
||||
)
|
||||
"#;
|
||||
let mut mock_ext = MockExt::default();
|
||||
assert_ok!(execute(&CODE_SR25519, vec![], &mut mock_ext));
|
||||
assert_eq!(mock_ext.sr25519_verify.into_inner(), [([1; 64], [1; 16].to_vec(), [1; 32])]);
|
||||
}
|
||||
|
||||
const CODE_GET_STORAGE: &str = r#"
|
||||
(module
|
||||
(import "seal0" "seal_get_storage" (func $seal_get_storage (param i32 i32 i32) (result i32)))
|
||||
|
||||
@@ -109,6 +109,8 @@ pub enum ReturnCode {
|
||||
/// ECDSA compressed pubkey conversion into Ethereum address failed (most probably
|
||||
/// wrong pubkey provided).
|
||||
EcdsaRecoverFailed = 11,
|
||||
/// sr25519 signature verification failed.
|
||||
Sr25519VerifyFailed = 12,
|
||||
}
|
||||
|
||||
impl From<ExecReturnValue> for ReturnCode {
|
||||
@@ -251,6 +253,8 @@ pub enum RuntimeCosts {
|
||||
HashBlake128(u32),
|
||||
/// Weight of calling `seal_ecdsa_recover`.
|
||||
EcdsaRecovery,
|
||||
/// Weight of calling `seal_sr25519_verify` for the given input size.
|
||||
Sr25519Verify(u32),
|
||||
/// Weight charged by a chain extension through `seal_call_chain_extension`.
|
||||
ChainExtension(Weight),
|
||||
/// Weight charged for calling into the runtime.
|
||||
@@ -336,6 +340,9 @@ impl RuntimeCosts {
|
||||
.hash_blake2_128
|
||||
.saturating_add(s.hash_blake2_128_per_byte.saturating_mul(len.into())),
|
||||
EcdsaRecovery => s.ecdsa_recover,
|
||||
Sr25519Verify(len) => s
|
||||
.sr25519_verify
|
||||
.saturating_add(s.sr25519_verify_per_byte.saturating_mul(len.into())),
|
||||
ChainExtension(weight) => weight,
|
||||
CallRuntime(weight) => weight,
|
||||
SetCodeHash => s.set_code_hash,
|
||||
@@ -2466,6 +2473,46 @@ pub mod env {
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify a sr25519 signature
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `signature_ptr`: the pointer into the linear memory where the signature is placed. Should
|
||||
/// be a value of 64 bytes.
|
||||
/// - `pub_key_ptr`: the pointer into the linear memory where the public key is placed. Should
|
||||
/// be a value of 32 bytes.
|
||||
/// - `message_len`: the length of the message payload.
|
||||
/// - `message_ptr`: the pointer into the linear memory where the message is placed.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// - `ReturnCode::Sr25519VerifyFailed
|
||||
#[unstable]
|
||||
fn sr25519_verify(
|
||||
ctx: _,
|
||||
memory: _,
|
||||
signature_ptr: u32,
|
||||
pub_key_ptr: u32,
|
||||
message_len: u32,
|
||||
message_ptr: u32,
|
||||
) -> Result<ReturnCode, TrapReason> {
|
||||
ctx.charge_gas(RuntimeCosts::Sr25519Verify(message_len))?;
|
||||
|
||||
let mut signature: [u8; 64] = [0; 64];
|
||||
ctx.read_sandbox_memory_into_buf(memory, signature_ptr, &mut signature)?;
|
||||
|
||||
let mut pub_key: [u8; 32] = [0; 32];
|
||||
ctx.read_sandbox_memory_into_buf(memory, pub_key_ptr, &mut pub_key)?;
|
||||
|
||||
let message: Vec<u8> = ctx.read_sandbox_memory(memory, message_ptr, message_len)?;
|
||||
|
||||
if ctx.ext.sr25519_verify(&signature, &message, &pub_key) {
|
||||
Ok(ReturnCode::Success)
|
||||
} else {
|
||||
Ok(ReturnCode::Sr25519VerifyFailed)
|
||||
}
|
||||
}
|
||||
|
||||
/// Replace the contract code at the specified address with new code.
|
||||
///
|
||||
/// # Note
|
||||
|
||||
Reference in New Issue
Block a user