Skip to content

Commit

Permalink
feat: add aptos signer
Browse files Browse the repository at this point in the history
  • Loading branch information
bluekirby1111 committed Feb 22, 2023
1 parent a96328b commit f8f8efe
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 96 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,14 @@ default-features = false
features = ["user-hooks"]

[features]
default = ["solana", "ethereum", "erc20", "cosmos", "arweave", "algorand"]
default = ["solana", "ethereum", "erc20", "cosmos", "arweave", "algorand", "aptos"]
arweave = ["arweave-rs"]
cosmos = ["secp256k1"]
erc20 = ["secp256k1", "web3"]
ethereum = ["secp256k1", "web3"]
solana = ["ed25519-dalek"]
algorand = ["ed25519-dalek"]
aptos = ["ed25519-dalek"]
build-binary = ["clap"]

[[bin]]
Expand Down
Binary file added res/test_bundles/aptos_sig
Binary file not shown.
27 changes: 27 additions & 0 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ use crate::Secp256k1Signer;
#[cfg(feature = "cosmos")]
use crate::CosmosSigner;

#[cfg(feature = "aptos")]
use crate::AptosSigner;

use crate::error::BundlrError;

#[derive(FromPrimitive, Display, PartialEq, Eq, Debug, Clone)]
Expand Down Expand Up @@ -51,6 +54,8 @@ impl From<u16> for SignerMap {
2 => SignerMap::ED25519,
3 => SignerMap::Ethereum,
4 => SignerMap::Solana,
5 => SignerMap::InjectedAptos,
6 => SignerMap::MultiAptos,
_ => panic!("Invalid signer map"),
}
}
Expand All @@ -63,6 +68,8 @@ impl SignerMap {
SignerMap::ED25519 => 2,
SignerMap::Ethereum => 3,
SignerMap::Solana => 4,
SignerMap::InjectedAptos => 5,
SignerMap::MultiAptos => 6,
_ => panic!("Invalid signer map"),
}
}
Expand Down Expand Up @@ -93,6 +100,18 @@ impl SignerMap {
pub_length: ed25519_dalek::PUBLIC_KEY_LENGTH,
sig_name: "solana".to_owned(),
},
#[cfg(feature = "aptos")]
SignerMap::InjectedAptos => Config {
sig_length: ed25519_dalek::SIGNATURE_LENGTH,
pub_length: ed25519_dalek::PUBLIC_KEY_LENGTH,
sig_name: "injectedAptos".to_owned(),
},
#[cfg(feature = "aptos")]
SignerMap::MultiAptos => Config {
sig_length: ed25519_dalek::SIGNATURE_LENGTH * 32 + 4, // max 32 64 byte signatures, +4 for 32-bit bitmap
pub_length: ed25519_dalek::PUBLIC_KEY_LENGTH * 32 + 1, // max 64 32 byte keys, +1 for 8-bit threshold value
sig_name: "multiAptos".to_owned(),
},
#[cfg(feature = "cosmos")]
SignerMap::Cosmos => Config {
sig_length: secp256k1::constants::COMPACT_SIGNATURE_SIZE,
Expand Down Expand Up @@ -130,6 +149,14 @@ impl SignerMap {
Bytes::copy_from_slice(message),
Bytes::copy_from_slice(signature),
),
#[cfg(feature = "aptos")]
SignerMap::InjectedAptos => AptosSigner::verify(
Bytes::copy_from_slice(pk),
Bytes::copy_from_slice(message),
Bytes::copy_from_slice(signature),
),
#[cfg(feature = "aptos")]
SignerMap::MultiAptos => todo!(),
#[cfg(feature = "cosmos")]
SignerMap::Cosmos => CosmosSigner::verify(
Bytes::copy_from_slice(pk),
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ pub use signers::secp256k1::Secp256k1Signer;

#[cfg(feature = "cosmos")]
pub use signers::cosmos::CosmosSigner;

#[cfg(feature = "aptos")]
pub use signers::aptos::AptosSigner;
116 changes: 116 additions & 0 deletions src/signers/aptos.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use crate::error::BundlrError;
use crate::Signer as SignerTrait;
use crate::Verifier as VerifierTrait;
use crate::{index::SignerMap, Ed25519Signer};

use bytes::Bytes;
use ed25519_dalek::Verifier;
use ed25519_dalek::{Keypair, PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH};

pub struct AptosSigner {
signer: Ed25519Signer,
}

impl AptosSigner {
pub fn new(keypair: Keypair) -> Self {
AptosSigner {
signer: Ed25519Signer::new(keypair),
}
}

pub fn from_base58(s: &str) -> Self {
Self {
signer: Ed25519Signer::from_base58(s),
}
}
}

const SIG_TYPE: SignerMap = SignerMap::ED25519;
const SIG_LENGTH: u16 = SIGNATURE_LENGTH as u16;
const PUB_LENGTH: u16 = PUBLIC_KEY_LENGTH as u16;

impl SignerTrait for AptosSigner {
fn sign(&self, message: bytes::Bytes) -> Result<bytes::Bytes, crate::error::BundlrError> {
let aptos_message =
Bytes::copy_from_slice(&[b"APTOS\nmessage: ".as_ref(), &message[..]].concat());
let nonce = Bytes::from(b"\nnonce: bundlr".to_vec());
let full_msg = Bytes::from([aptos_message, nonce].concat());
self.signer.sign(full_msg)
}

fn pub_key(&self) -> bytes::Bytes {
self.signer.pub_key()
}

fn sig_type(&self) -> SignerMap {
SIG_TYPE
}
fn get_sig_length(&self) -> u16 {
SIG_LENGTH
}
fn get_pub_length(&self) -> u16 {
PUB_LENGTH
}
}

impl VerifierTrait for AptosSigner {
fn verify(
pk: Bytes,
message: Bytes,
signature: Bytes,
) -> Result<bool, crate::error::BundlrError> {
let public_key = ed25519_dalek::PublicKey::from_bytes(&pk).unwrap_or_else(|_| {
panic!(
"ED25519 public keys must be {} bytes long",
ed25519_dalek::PUBLIC_KEY_LENGTH
)
});
let sig = ed25519_dalek::Signature::from_bytes(&signature).unwrap_or_else(|_| {
panic!(
"ED22519 signatures keys must be {} bytes long",
ed25519_dalek::SIGNATURE_LENGTH
)
});
let aptos_message =
Bytes::copy_from_slice(&[b"APTOS\nmessage: ".as_ref(), &message[..]].concat());
let nonce = Bytes::from(b"\nnonce: bundlr".to_vec());
let full_msg = Bytes::from([aptos_message, nonce].concat());

public_key
.verify(&full_msg, &sig)
.map(|_| true)
.map_err(|_| BundlrError::InvalidSignature)
}
}

#[cfg(test)]
mod tests {
use crate::{AptosSigner, Signer, Verifier};
use bytes::Bytes;
use ed25519_dalek::Keypair;

#[test]
fn should_sign_and_verify() {
let msg = Bytes::from(b"Message".to_vec());

let base58_secret_key = "kNykCXNxgePDjFbDWjPNvXQRa8U12Ywc19dFVaQ7tebUj3m7H4sF4KKdJwM7yxxb3rqxchdjezX9Szh8bLcQAjb";
let signer = AptosSigner::from_base58(base58_secret_key);
let sig = signer.sign(msg.clone()).unwrap();
let pub_key = signer.pub_key();
println!("{:?}", pub_key.to_vec());
assert!(AptosSigner::verify(pub_key, msg.clone(), sig).unwrap());

let keypair = Keypair::from_bytes(&[
237, 158, 92, 107, 132, 192, 1, 57, 8, 20, 213, 108, 29, 227, 37, 8, 3, 105, 196, 244,
8, 221, 184, 199, 62, 253, 98, 131, 33, 165, 165, 215, 14, 7, 46, 23, 221, 242, 240,
226, 94, 79, 161, 31, 192, 163, 13, 25, 106, 53, 34, 215, 83, 124, 162, 156, 8, 97,
194, 180, 213, 179, 33, 68,
])
.unwrap();
let signer = AptosSigner::new(keypair);
let sig = signer.sign(msg.clone()).unwrap();
let pub_key = signer.pub_key();

assert!(AptosSigner::verify(pub_key, msg, sig).unwrap());
}
}
4 changes: 3 additions & 1 deletion src/signers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use crate::{error::BundlrError, index::SignerMap};
use bytes::Bytes;

#[cfg(feature = "aptos")]
pub mod aptos;
#[cfg(feature = "arweave")]
pub mod arweave;
#[cfg(feature = "cosmos")]
pub mod cosmos;
#[cfg(any(feature = "solana", feature = "algorand"))]
#[cfg(any(feature = "solana", feature = "algorand", feature = "aptos"))]
pub mod ed25519;
#[cfg(any(feature = "ethereum", feature = "erc20"))]
pub mod secp256k1;
Expand Down
2 changes: 0 additions & 2 deletions src/transaction/bundlr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ impl BundlrTx {
let (bundlr_tx, data_start) =
BundlrTx::from_info_bytes(&buffer).expect("Could not gather info from bytes");
let data = &buffer[data_start..buffer.len()];
println!("data: {:?}", data);

Ok(BundlrTx {
data: Data::Bytes(data.to_vec()),
Expand Down Expand Up @@ -282,7 +281,6 @@ impl BundlrTx {

pub async fn verify(&mut self) -> Result<bool, BundlrError> {
let message = self.get_message().await;
println!("msg: {:?}", message.to_vec());
let pub_key = &self.owner;
let signature = &self.signature;

Expand Down
Loading

0 comments on commit f8f8efe

Please sign in to comment.