733 lines
20 KiB
Diff
733 lines
20 KiB
Diff
Index: Cargo.lock
|
|
IDEA additional info:
|
|
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
|
<+>UTF-8
|
|
===================================================================
|
|
--- Cargo.lock (revision d84010e4afe5f79c812ff7da349460dc690a8392)
|
|
+++ Cargo.lock (revision aa30fbafe08be98cfbea6772040d5f3b073877b0)
|
|
@@ -274,12 +274,22 @@
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
|
|
dependencies = [
|
|
- "block-padding",
|
|
+ "block-padding 0.1.5",
|
|
"byte-tools",
|
|
"byteorder",
|
|
"generic-array 0.12.3",
|
|
]
|
|
|
|
+[[package]]
|
|
+name = "block-buffer"
|
|
+version = "0.9.0"
|
|
+source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
+checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
|
|
+dependencies = [
|
|
+ "block-padding 0.2.1",
|
|
+ "generic-array 0.14.3",
|
|
+]
|
|
+
|
|
[[package]]
|
|
name = "block-padding"
|
|
version = "0.1.5"
|
|
@@ -289,6 +299,12 @@
|
|
"byte-tools",
|
|
]
|
|
|
|
+[[package]]
|
|
+name = "block-padding"
|
|
+version = "0.2.1"
|
|
+source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
+checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
|
|
+
|
|
[[package]]
|
|
name = "bs58"
|
|
version = "0.3.1"
|
|
@@ -633,6 +649,12 @@
|
|
"lazy_static",
|
|
]
|
|
|
|
+[[package]]
|
|
+name = "crunchy"
|
|
+version = "0.2.2"
|
|
+source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
+checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
|
+
|
|
[[package]]
|
|
name = "crypto-mac"
|
|
version = "0.7.0"
|
|
@@ -682,7 +704,7 @@
|
|
checksum = "5d85653f070353a16313d0046f173f70d1aadd5b42600a14de626f0dfb3473a5"
|
|
dependencies = [
|
|
"byteorder",
|
|
- "digest",
|
|
+ "digest 0.8.1",
|
|
"rand_core 0.5.1",
|
|
"subtle 2.2.2",
|
|
"zeroize",
|
|
@@ -725,6 +747,15 @@
|
|
"generic-array 0.12.3",
|
|
]
|
|
|
|
+[[package]]
|
|
+name = "digest"
|
|
+version = "0.9.0"
|
|
+source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
+checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
|
|
+dependencies = [
|
|
+ "generic-array 0.14.3",
|
|
+]
|
|
+
|
|
[[package]]
|
|
name = "dir-diff"
|
|
version = "0.3.2"
|
|
@@ -1316,7 +1347,18 @@
|
|
checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695"
|
|
dependencies = [
|
|
"crypto-mac",
|
|
- "digest",
|
|
+ "digest 0.8.1",
|
|
+]
|
|
+
|
|
+[[package]]
|
|
+name = "hmac-drbg"
|
|
+version = "0.2.0"
|
|
+source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
+checksum = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b"
|
|
+dependencies = [
|
|
+ "digest 0.8.1",
|
|
+ "generic-array 0.12.3",
|
|
+ "hmac",
|
|
]
|
|
|
|
[[package]]
|
|
@@ -1750,6 +1792,12 @@
|
|
"ws",
|
|
]
|
|
|
|
+[[package]]
|
|
+name = "keccak"
|
|
+version = "0.1.0"
|
|
+source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
+checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7"
|
|
+
|
|
[[package]]
|
|
name = "kernel32-sys"
|
|
version = "0.2.2"
|
|
@@ -1818,6 +1866,22 @@
|
|
"libc",
|
|
]
|
|
|
|
+[[package]]
|
|
+name = "libsecp256k1"
|
|
+version = "0.3.5"
|
|
+source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
+checksum = "1fc1e2c808481a63dc6da2074752fdd4336a3c8fcc68b83db6f1fd5224ae7962"
|
|
+dependencies = [
|
|
+ "arrayref",
|
|
+ "crunchy",
|
|
+ "digest 0.8.1",
|
|
+ "hmac-drbg",
|
|
+ "rand 0.7.3",
|
|
+ "sha2",
|
|
+ "subtle 2.2.2",
|
|
+ "typenum",
|
|
+]
|
|
+
|
|
[[package]]
|
|
name = "linked-hash-map"
|
|
version = "0.5.3"
|
|
@@ -2146,6 +2210,12 @@
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
|
|
|
+[[package]]
|
|
+name = "opaque-debug"
|
|
+version = "0.3.0"
|
|
+source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
+checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
|
+
|
|
[[package]]
|
|
name = "openssl"
|
|
version = "0.10.29"
|
|
@@ -3098,10 +3168,10 @@
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
|
|
dependencies = [
|
|
- "block-buffer",
|
|
- "digest",
|
|
+ "block-buffer 0.7.3",
|
|
+ "digest 0.8.1",
|
|
"fake-simd",
|
|
- "opaque-debug",
|
|
+ "opaque-debug 0.2.3",
|
|
]
|
|
|
|
[[package]]
|
|
@@ -3116,10 +3186,22 @@
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69"
|
|
dependencies = [
|
|
- "block-buffer",
|
|
- "digest",
|
|
+ "block-buffer 0.7.3",
|
|
+ "digest 0.8.1",
|
|
"fake-simd",
|
|
- "opaque-debug",
|
|
+ "opaque-debug 0.2.3",
|
|
+]
|
|
+
|
|
+[[package]]
|
|
+name = "sha3"
|
|
+version = "0.9.1"
|
|
+source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
+checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809"
|
|
+dependencies = [
|
|
+ "block-buffer 0.9.0",
|
|
+ "digest 0.9.0",
|
|
+ "keccak",
|
|
+ "opaque-debug 0.3.0",
|
|
]
|
|
|
|
[[package]]
|
|
@@ -3376,12 +3458,16 @@
|
|
name = "solana-bpf-loader-program"
|
|
version = "1.4.0"
|
|
dependencies = [
|
|
+ "arrayref",
|
|
"bincode",
|
|
"byteorder",
|
|
+ "hex",
|
|
+ "libsecp256k1",
|
|
"num-derive 0.3.0",
|
|
"num-traits",
|
|
"rand 0.7.3",
|
|
"rustversion",
|
|
+ "sha3",
|
|
"solana-runtime",
|
|
"solana-sdk 1.4.0",
|
|
"solana_rbpf",
|
|
Index: programs/bpf_loader/Cargo.toml
|
|
IDEA additional info:
|
|
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
|
<+>UTF-8
|
|
===================================================================
|
|
--- programs/bpf_loader/Cargo.toml (revision d84010e4afe5f79c812ff7da349460dc690a8392)
|
|
+++ programs/bpf_loader/Cargo.toml (revision aa30fbafe08be98cfbea6772040d5f3b073877b0)
|
|
@@ -17,6 +17,10 @@
|
|
solana-sdk = { path = "../../sdk", version = "1.4.0" }
|
|
solana_rbpf = "=0.1.28"
|
|
thiserror = "1.0"
|
|
+libsecp256k1 = "0.3.5"
|
|
+sha3 = "0.9.1"
|
|
+arrayref = "0.3.6"
|
|
+hex = "0.4.2"
|
|
|
|
[dev-dependencies]
|
|
rand = "0.7.3"
|
|
Index: programs/bpf_loader/src/crypto.rs
|
|
IDEA additional info:
|
|
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
|
<+>UTF-8
|
|
===================================================================
|
|
--- programs/bpf_loader/src/crypto.rs (revision aa30fbafe08be98cfbea6772040d5f3b073877b0)
|
|
+++ programs/bpf_loader/src/crypto.rs (revision aa30fbafe08be98cfbea6772040d5f3b073877b0)
|
|
@@ -0,0 +1,171 @@
|
|
+pub extern crate secp256k1;
|
|
+
|
|
+use std::io::Write;
|
|
+
|
|
+use num_traits::AsPrimitive;
|
|
+use secp256k1::curve::{Affine, ECMULT_CONTEXT, ECMULT_GEN_CONTEXT, ECMultGenContext, Field, Jacobian, Scalar};
|
|
+use sha3::Digest;
|
|
+
|
|
+use self::secp256k1::{Error, PublicKey};
|
|
+
|
|
+pub enum SchnorrError {
|
|
+ InvalidPubKey
|
|
+}
|
|
+
|
|
+#[repr(C)]
|
|
+pub struct EcrecoverInput {
|
|
+ pub signature: [u8; 65],
|
|
+ pub message: [u8; 32],
|
|
+}
|
|
+
|
|
+#[repr(C)]
|
|
+pub struct EcrecoverOutput {
|
|
+ pub address: [u8; 20],
|
|
+}
|
|
+
|
|
+#[repr(C)]
|
|
+pub struct SchnorrifyInput {
|
|
+ message: [u8; 32],
|
|
+ addr: [u8; 20],
|
|
+ signature: [u8; 32],
|
|
+ pub_key: [u8; 64],
|
|
+}
|
|
+
|
|
+impl SchnorrifyInput {
|
|
+ pub fn verify(&self) -> bool {
|
|
+ let sig = SchnorrSignature {
|
|
+ address: self.addr,
|
|
+ signature: self.signature,
|
|
+ };
|
|
+
|
|
+ let pub_key = SchnorrPublicKey::deserialize(&self.pub_key);
|
|
+
|
|
+ match sig.verify_signature(&self.message, &pub_key) {
|
|
+ Ok(res) => res,
|
|
+ Err(_) => false
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+pub struct SchnorrPublicKey {
|
|
+ x: Field,
|
|
+ y: Field,
|
|
+}
|
|
+
|
|
+pub struct SchnorrSignature {
|
|
+ pub address: [u8; 20],
|
|
+ pub signature: [u8; 32],
|
|
+}
|
|
+
|
|
+impl SchnorrPublicKey {
|
|
+ pub fn deserialize(d: &[u8; 64]) -> SchnorrPublicKey {
|
|
+ let mut x = Field::default();
|
|
+ let mut y = Field::default();
|
|
+ x.set_b32(array_ref![d,0,32]);
|
|
+ y.set_b32(array_ref![d,32,32]);
|
|
+ x.normalize();
|
|
+ y.normalize();
|
|
+ SchnorrPublicKey {
|
|
+ x,
|
|
+ y,
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+impl SchnorrSignature {
|
|
+ pub fn verify_signature(&self, msg: &[u8; 32], pub_key: &SchnorrPublicKey) -> Result<bool, SchnorrError> {
|
|
+ let mut af = Affine::default();
|
|
+ af.set_xy(&pub_key.x, &pub_key.y);
|
|
+ let mut pubkey_j: Jacobian = Jacobian::default();
|
|
+ pubkey_j.set_ge(&af);
|
|
+
|
|
+ // Verify that the pubkey is a curve point
|
|
+ let mut elem = Affine::default();
|
|
+ if !elem.set_xo_var(&pub_key.x, pub_key.y.is_odd()) {
|
|
+ return Err(SchnorrError::InvalidPubKey);
|
|
+ }
|
|
+ elem.y.normalize();
|
|
+
|
|
+ // Make sure that the ordinates are equal
|
|
+ if elem.y.b32() != pub_key.y.b32() {
|
|
+ return Err(SchnorrError::InvalidPubKey);
|
|
+ }
|
|
+
|
|
+ // Generate the challenge
|
|
+ let mut h = sha3::Keccak256::default();
|
|
+ h.write(&pub_key.x.b32()); // pub key x coordinate
|
|
+ h.write(&[(pub_key.y.is_odd()).as_()]); // y parity
|
|
+ h.write(msg); // msg
|
|
+ h.write(&self.address); // nonceTimesGeneratorAddress
|
|
+ let challenge = h.finalize();
|
|
+
|
|
+ let mut e = Scalar::default();
|
|
+ e.set_b32(array_ref![challenge,0,32]);
|
|
+
|
|
+ let mut s = Scalar::default();
|
|
+ s.set_b32(&self.signature);
|
|
+
|
|
+ // Calculate s x G + e x P
|
|
+ let mut k: Jacobian = Jacobian::default();
|
|
+ ECMULT_CONTEXT.ecmult(&mut k, &pubkey_j, &e, &s);
|
|
+
|
|
+ let r = jacobian_to_normalized_affine(&k);
|
|
+
|
|
+ // Generate Ethereum address from calculated point
|
|
+ let eth_addr = affine_to_eth_address(&r);
|
|
+
|
|
+ // Verify that addr(k) == sig.address
|
|
+ Ok(eth_addr == self.address)
|
|
+ }
|
|
+}
|
|
+
|
|
+fn affine_to_eth_address(a: &Affine) -> [u8; 20] {
|
|
+ let mut h = sha3::Keccak256::default();
|
|
+ h.write(a.x.b32().as_ref()); // result key x coordinate
|
|
+ h.write(a.y.b32().as_ref()); // result key y coordinate
|
|
+
|
|
+ let out = h.finalize();
|
|
+ let mut out_addr = [0; 20];
|
|
+ out_addr.copy_from_slice(&out[12..]);
|
|
+
|
|
+ out_addr
|
|
+}
|
|
+
|
|
+fn jacobian_to_normalized_affine(j: &Jacobian) -> Affine {
|
|
+ let mut r = Affine::default();
|
|
+ r.set_gej(j);
|
|
+ r.x.normalize();
|
|
+ r.y.normalize();
|
|
+
|
|
+ r
|
|
+}
|
|
+
|
|
+#[cfg(test)]
|
|
+mod tests {
|
|
+ use std::io::Write;
|
|
+
|
|
+ use hex;
|
|
+
|
|
+ use crate::crypto::{SchnorrPublicKey, SchnorrSignature};
|
|
+
|
|
+ #[test]
|
|
+ fn verify_signature() {
|
|
+ let msggg = hex::decode("0194fdc2fa2ffcc041d3ff12045b73c86e4ff95ff662a5eee82abdf44a2d0b75").unwrap();
|
|
+ let siggg = hex::decode("ee5884a66454baca985f4453c05394214a75dc38956ea39f12cc429f081aae4b").unwrap();
|
|
+ let addr = hex::decode("9addd8a38fea7e1b94550e5bc249309a633dfa63").unwrap();
|
|
+ let pb = hex::decode("ae92ce7553993f04400c6976f8cd4540ae076bf0131eec8b35ae0ff9fc577a901de834d0f62ae6ecbeec2124595b06bce078b8133b4dda3855cf346feb2b2ca2").unwrap();
|
|
+
|
|
+ let sig = SchnorrSignature {
|
|
+ address: *array_ref![addr,0,20],
|
|
+ signature: *array_ref![siggg,0,32],
|
|
+ };
|
|
+
|
|
+ let pub_key = SchnorrPublicKey::deserialize(array_ref![pb,0,64]);
|
|
+
|
|
+ let msg = array_ref![msggg,0,32];
|
|
+ match sig.verify_signature(msg, &pub_key) {
|
|
+ Ok(res) => assert!(res, "signature should be valid"),
|
|
+ Err(err) => assert!(false, "signature verification failed")
|
|
+ }
|
|
+ }
|
|
+}
|
|
Index: programs/bpf_loader/src/lib.rs
|
|
IDEA additional info:
|
|
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
|
<+>UTF-8
|
|
===================================================================
|
|
--- programs/bpf_loader/src/lib.rs (revision d84010e4afe5f79c812ff7da349460dc690a8392)
|
|
+++ programs/bpf_loader/src/lib.rs (revision aa30fbafe08be98cfbea6772040d5f3b073877b0)
|
|
@@ -4,6 +4,10 @@
|
|
pub mod deprecated;
|
|
pub mod serialization;
|
|
pub mod syscalls;
|
|
+pub mod crypto;
|
|
+
|
|
+#[macro_use]
|
|
+extern crate arrayref;
|
|
|
|
use crate::{
|
|
bpf_verifier::VerifierError,
|
|
Index: programs/bpf_loader/src/syscalls.rs
|
|
IDEA additional info:
|
|
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
|
<+>UTF-8
|
|
===================================================================
|
|
--- programs/bpf_loader/src/syscalls.rs (revision d84010e4afe5f79c812ff7da349460dc690a8392)
|
|
+++ programs/bpf_loader/src/syscalls.rs (revision aa30fbafe08be98cfbea6772040d5f3b073877b0)
|
|
@@ -1,10 +1,23 @@
|
|
-use crate::{alloc, BPFError};
|
|
-use alloc::Alloc;
|
|
+use std::{
|
|
+ alloc::Layout,
|
|
+ cell::{RefCell, RefMut},
|
|
+ convert::TryFrom,
|
|
+ mem::{align_of, size_of},
|
|
+ rc::Rc,
|
|
+ slice::from_raw_parts_mut,
|
|
+ str::{from_utf8, Utf8Error},
|
|
+};
|
|
+
|
|
+use secp256k1::{Error, PublicKey, RecoveryId, Signature};
|
|
+use sha3::Digest;
|
|
use solana_rbpf::{
|
|
- ebpf::{EbpfError, SyscallObject, ELF_INSN_DUMP_OFFSET, MM_HEAP_START},
|
|
- memory_region::{translate_addr, MemoryRegion},
|
|
+ ebpf::{EbpfError, ELF_INSN_DUMP_OFFSET, MM_HEAP_START, SyscallObject},
|
|
EbpfVm,
|
|
+ memory_region::{MemoryRegion, translate_addr},
|
|
};
|
|
+use thiserror::Error as ThisError;
|
|
+
|
|
+use alloc::Alloc;
|
|
use solana_runtime::message_processor::MessageProcessor;
|
|
use solana_sdk::{
|
|
account::Account,
|
|
@@ -18,16 +31,16 @@
|
|
program_error::ProgramError,
|
|
pubkey::{Pubkey, PubkeyError},
|
|
};
|
|
-use std::{
|
|
- alloc::Layout,
|
|
- cell::{RefCell, RefMut},
|
|
- convert::TryFrom,
|
|
- mem::{align_of, size_of},
|
|
- rc::Rc,
|
|
- slice::from_raw_parts_mut,
|
|
- str::{from_utf8, Utf8Error},
|
|
-};
|
|
-use thiserror::Error as ThisError;
|
|
+
|
|
+use crate::{alloc, BPFError};
|
|
+/// Program heap allocators are intended to allocate/free from a given
|
|
+/// chunk of memory. The specific allocator implementation is
|
|
+/// selectable at build-time.
|
|
+/// Only one allocator is currently supported
|
|
+
|
|
+/// Simple bump allocator, never frees
|
|
+use crate::allocator_bump::BPFAllocator;
|
|
+use crate::crypto::{EcrecoverInput, EcrecoverOutput, SchnorrifyInput};
|
|
|
|
/// Error definitions
|
|
#[derive(Debug, ThisError)]
|
|
@@ -53,20 +66,13 @@
|
|
#[error("Unaligned pointer")]
|
|
UnalignedPointer,
|
|
}
|
|
+
|
|
impl From<SyscallError> for EbpfError<BPFError> {
|
|
fn from(error: SyscallError) -> Self {
|
|
EbpfError::UserError(error.into())
|
|
}
|
|
}
|
|
|
|
-/// Program heap allocators are intended to allocate/free from a given
|
|
-/// chunk of memory. The specific allocator implementation is
|
|
-/// selectable at build-time.
|
|
-/// Only one allocator is currently supported
|
|
-
|
|
-/// Simple bump allocator, never frees
|
|
-use crate::allocator_bump::BPFAllocator;
|
|
-
|
|
/// Default program heap size, allocators
|
|
/// are expected to enforce this
|
|
const DEFAULT_HEAP_SIZE: usize = 32 * 1024;
|
|
@@ -114,6 +120,20 @@
|
|
invoke_context: invoke_context.clone(),
|
|
}),
|
|
)?;
|
|
+
|
|
+ // Signature verification
|
|
+ vm.register_syscall_with_context_ex(
|
|
+ "sol_verify_ethschnorr",
|
|
+ Box::new(SyscallSchorrify {
|
|
+ invoke_context: invoke_context.clone(),
|
|
+ }),
|
|
+ )?;
|
|
+ vm.register_syscall_with_context_ex(
|
|
+ "sol_ecrecover",
|
|
+ Box::new(SyscallEcrecover {
|
|
+ invoke_context: invoke_context.clone(),
|
|
+ }),
|
|
+ )?;
|
|
|
|
// Memory allocator
|
|
let heap = vec![0_u8; DEFAULT_HEAP_SIZE];
|
|
@@ -256,6 +276,7 @@
|
|
pub struct SyscallLog {
|
|
logger: Rc<RefCell<dyn Logger>>,
|
|
}
|
|
+
|
|
impl SyscallObject<BPFError> for SyscallLog {
|
|
fn call(
|
|
&mut self,
|
|
@@ -285,6 +306,7 @@
|
|
pub struct SyscallLogU64 {
|
|
logger: Rc<RefCell<dyn Logger>>,
|
|
}
|
|
+
|
|
impl SyscallObject<BPFError> for SyscallLogU64 {
|
|
fn call(
|
|
&mut self,
|
|
@@ -319,6 +341,7 @@
|
|
pub struct SyscallSolAllocFree {
|
|
allocator: BPFAllocator,
|
|
}
|
|
+
|
|
impl SyscallObject<BPFError> for SyscallSolAllocFree {
|
|
fn call(
|
|
&mut self,
|
|
@@ -373,6 +396,105 @@
|
|
Ok(0)
|
|
}
|
|
|
|
+/// Verify a ETH optimized Schnorr Signature
|
|
+pub struct SyscallEcrecover<'a> {
|
|
+ invoke_context: Rc<RefCell<&'a mut dyn InvokeContext>>,
|
|
+}
|
|
+
|
|
+impl<'a> SyscallEcrecover<'a> {
|
|
+ fn get_context_mut(&self) -> Result<RefMut<&'a mut dyn InvokeContext>, EbpfError<BPFError>> {
|
|
+ self.invoke_context
|
|
+ .try_borrow_mut()
|
|
+ .map_err(|_| SyscallError::InvokeContextBorrowFailed.into())
|
|
+ }
|
|
+}
|
|
+
|
|
+impl<'a> SyscallObject<BPFError> for SyscallEcrecover<'a> {
|
|
+ fn call(
|
|
+ &mut self,
|
|
+ input: u64,
|
|
+ output: u64,
|
|
+ _arg3: u64,
|
|
+ _arg4: u64,
|
|
+ _arg5: u64,
|
|
+ ro_regions: &[MemoryRegion],
|
|
+ _rw_regions: &[MemoryRegion],
|
|
+ ) -> Result<u64, EbpfError<BPFError>> {
|
|
+ let input = translate_type!(
|
|
+ EcrecoverInput,
|
|
+ input,
|
|
+ ro_regions
|
|
+ )?;
|
|
+
|
|
+ let mut output = translate_type_mut!(
|
|
+ EcrecoverOutput,
|
|
+ output,
|
|
+ ro_regions
|
|
+ )?;
|
|
+
|
|
+ let signature = match secp256k1::Signature::parse_slice(&input.signature[..64]) {
|
|
+ Ok(v) => v,
|
|
+ Err(_) => {
|
|
+ return Ok(0);
|
|
+ }
|
|
+ };
|
|
+
|
|
+ let recovery_id = match secp256k1::RecoveryId::parse(input.signature[64]) {
|
|
+ Ok(v) => v,
|
|
+ Err(_) => { return Ok(0); }
|
|
+ };
|
|
+
|
|
+ match secp256k1::recover(&secp256k1::Message::parse(&input.message), &signature,
|
|
+ &recovery_id) {
|
|
+ Ok(v) => {
|
|
+ let mut addr = [0u8; 20];
|
|
+ addr.copy_from_slice(&sha3::Keccak256::digest(&v.serialize())[12..]);
|
|
+ output.address = addr;
|
|
+ }
|
|
+ Err(_) => {
|
|
+ return Ok(0);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ Ok(1)
|
|
+ }
|
|
+}
|
|
+
|
|
+/// Verify a ETH optimized Schnorr Signature
|
|
+pub struct SyscallSchorrify<'a> {
|
|
+ invoke_context: Rc<RefCell<&'a mut dyn InvokeContext>>,
|
|
+}
|
|
+
|
|
+impl<'a> SyscallSchorrify<'a> {
|
|
+ fn get_context_mut(&self) -> Result<RefMut<&'a mut dyn InvokeContext>, EbpfError<BPFError>> {
|
|
+ self.invoke_context
|
|
+ .try_borrow_mut()
|
|
+ .map_err(|_| SyscallError::InvokeContextBorrowFailed.into())
|
|
+ }
|
|
+}
|
|
+
|
|
+impl<'a> SyscallObject<BPFError> for SyscallSchorrify<'a> {
|
|
+ fn call(
|
|
+ &mut self,
|
|
+ addr: u64,
|
|
+ _arg2: u64,
|
|
+ _arg3: u64,
|
|
+ _arg4: u64,
|
|
+ _arg5: u64,
|
|
+ ro_regions: &[MemoryRegion],
|
|
+ _rw_regions: &[MemoryRegion],
|
|
+ ) -> Result<u64, EbpfError<BPFError>> {
|
|
+ let input = translate_type!(
|
|
+ SchnorrifyInput,
|
|
+ addr,
|
|
+ ro_regions
|
|
+ )?;
|
|
+ let res = input.verify();
|
|
+
|
|
+ Ok(res as u64)
|
|
+ }
|
|
+}
|
|
+
|
|
// Cross-program invocation syscalls
|
|
|
|
struct AccountReferences<'a> {
|
|
@@ -415,6 +537,7 @@
|
|
callers_keyed_accounts: &'a [KeyedAccount<'a>],
|
|
invoke_context: Rc<RefCell<&'a mut dyn InvokeContext>>,
|
|
}
|
|
+
|
|
impl<'a> SyscallProcessInstruction<'a> for SyscallProcessInstructionRust<'a> {
|
|
fn get_context_mut(&self) -> Result<RefMut<&'a mut dyn InvokeContext>, EbpfError<BPFError>> {
|
|
self.invoke_context
|
|
@@ -436,7 +559,7 @@
|
|
ix.accounts.len(),
|
|
ro_regions
|
|
)?
|
|
- .to_vec();
|
|
+ .to_vec();
|
|
let data = translate_slice!(u8, ix.data.as_ptr(), ix.data.len(), ro_regions)?.to_vec();
|
|
Ok(Instruction {
|
|
program_id: ix.program_id,
|
|
@@ -551,6 +674,7 @@
|
|
}
|
|
}
|
|
}
|
|
+
|
|
impl<'a> SyscallObject<BPFError> for SyscallProcessInstructionRust<'a> {
|
|
fn call(
|
|
&mut self,
|
|
@@ -626,6 +750,7 @@
|
|
callers_keyed_accounts: &'a [KeyedAccount<'a>],
|
|
invoke_context: Rc<RefCell<&'a mut dyn InvokeContext>>,
|
|
}
|
|
+
|
|
impl<'a> SyscallProcessInstruction<'a> for SyscallProcessSolInstructionC<'a> {
|
|
fn get_context_mut(&self) -> Result<RefMut<&'a mut dyn InvokeContext>, EbpfError<BPFError>> {
|
|
self.invoke_context
|
|
@@ -763,6 +888,7 @@
|
|
}
|
|
}
|
|
}
|
|
+
|
|
impl<'a> SyscallObject<BPFError> for SyscallProcessSolInstructionC<'a> {
|
|
fn call(
|
|
&mut self,
|
|
@@ -814,10 +940,10 @@
|
|
}
|
|
|
|
if account.is_signer && // If message indicates account is signed
|
|
- !( // one of the following needs to be true:
|
|
- keyed_account.signer_key().is_some() // Signed in the parent instruction
|
|
- || signers.contains(&account.pubkey) // Signed by the program
|
|
- ) {
|
|
+ !( // one of the following needs to be true:
|
|
+ keyed_account.signer_key().is_some() // Signed in the parent instruction
|
|
+ || signers.contains(&account.pubkey) // Signed by the program
|
|
+ ) {
|
|
return Err(SyscallError::PrivilegeEscalation.into());
|
|
}
|
|
}
|
|
@@ -1034,7 +1160,7 @@
|
|
assert_eq!(string, "Gaggablaghblagh!");
|
|
Ok(42)
|
|
})
|
|
- .unwrap()
|
|
+ .unwrap()
|
|
);
|
|
}
|
|
|
|
@@ -1066,7 +1192,7 @@
|
|
&[ro_region],
|
|
&[rw_region],
|
|
)
|
|
- .unwrap();
|
|
+ .unwrap();
|
|
}
|
|
|
|
#[test]
|