implementing script singing in progress

This commit is contained in:
debris 2016-09-12 15:09:32 +02:00
parent 2ac5ee73d3
commit 93ef222a25
8 changed files with 137 additions and 21 deletions

View File

@ -19,6 +19,7 @@ pub mod hash;
pub mod merkle_root;
pub mod network;
pub mod reader;
pub mod sign;
pub mod stream;
pub mod transaction;

View File

@ -20,7 +20,7 @@ impl Builder {
self
}
pub fn push_num(mut self, num: Num) -> Self {
pub fn push_num(self, num: Num) -> Self {
self.push_data(&num.to_vec())
}

View File

@ -7,11 +7,47 @@ use script::{script, Script, Num, VerificationFlags, Opcode, Error, read_usize};
#[derive(Debug, PartialEq, Clone, Copy)]
#[repr(u8)]
pub enum SignatureHash {
pub enum SighashBase {
All = 1,
None = 2,
Single = 3,
AnyoneCanPay = 0x80,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Sighash {
base: SighashBase,
anyone_can_pay: bool,
}
impl From<Sighash> for u8 {
fn from(s: Sighash) -> Self {
let base = s.base as u8;
match s.anyone_can_pay {
true => base | 0x80,
false => base,
}
}
}
impl Sighash {
fn from_u8(u: u8) -> Option<Self> {
let (base, anyone_can_pay) = match u {
1 => (SighashBase::All, false),
2 => (SighashBase::None, false),
3 => (SighashBase::Single, false),
0x81 => (SighashBase::All, true),
0x82 => (SighashBase::None, true),
0x83 => (SighashBase::Single, true),
_ => return None,
};
let sighash = Sighash {
base: base,
anyone_can_pay: anyone_can_pay
};
Some(sighash)
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
@ -79,10 +115,7 @@ impl SignatureChecker for TransactionSignatureChecker {
return false;
}
let hash_type = script_signature.last().unwrap();
let _hash_type = script_signature.last().unwrap();
unimplemented!();
}
@ -98,18 +131,18 @@ impl SignatureChecker for TransactionSignatureChecker {
}
fn signature_hash(
script_code: &Script,
_script_code: &Script,
tx: &Transaction,
i: usize,
hash_type: i32,
amount: u32,
version: SignatureVersion
_amount: u32,
_version: SignatureVersion
) -> H256 {
if i >= tx.transaction_inputs().len() {
return h256_from_u8(1);
}
if (hash_type & 0x1f) == SignatureHash::Single as i32 {
if (hash_type & 0x1f) == SighashBase::Single as i32 {
if i >= tx.transaction_outputs().len() {
return h256_from_u8(1);
}
@ -241,11 +274,7 @@ fn is_defined_hashtype_signature(sig: &[u8]) -> bool {
return false;
}
let n_hashtype = sig[sig.len() -1] & !(SignatureHash::AnyoneCanPay as u8);
if n_hashtype < SignatureHash::All as u8 && n_hashtype > SignatureHash::Single as u8 {
return false
}
true
Sighash::from_u8(sig[sig.len() -1]).is_some()
}
fn check_signature_encoding(sig: &[u8], flags: &VerificationFlags) -> Result<(), Error> {

View File

@ -11,7 +11,7 @@ mod standard;
pub use self::builder::Builder;
pub use self::error::Error;
pub use self::flags::VerificationFlags;
pub use self::interpreter::eval_script;
pub use self::interpreter::{eval_script, Sighash};
pub use self::opcode::Opcode;
pub use self::num::Num;
pub use self::script::{Script, ScriptWitness, read_usize};

View File

@ -2,7 +2,7 @@
use std::fmt;
use hex::ToHex;
use script::{Opcode, Error, Num};
use script::{Opcode, Error};
/// Maximum number of bytes pushable to the stack
const MAX_SCRIPT_ELEMENT_SIZE: usize = 520;
@ -172,7 +172,7 @@ impl fmt::Display for Script {
}
pub struct ScriptWitness {
script: Vec<Vec<u8>>,
_script: Vec<Vec<u8>>,
}
#[cfg(test)]
@ -225,4 +225,16 @@ OP_ADD
"#;
assert_eq!(script.to_string(), s.to_string());
}
//#[test]
//#[ignore]
//fn playpen() {
//let hex = "47304402202cb265bf10707bf49346c3515dd3d16fc454618c58ec0a0ff448a676c54ff71302206c6624d762a1fcef4618284ead8f08678ac05b13c84235f1654e6ad168233e8201410414e301b2328f17442c0b8310d787bf3d8a404cfbd0704f135b6ad4b2d3ee751310f981926e53a6e8c39bd7d3fefd576c543cce493cbac06388f2651d1aacbfcd".from_hex().unwrap();
//let script = Script::new(hex);
//let hex2 = "76a914c8e90996c7c6080ee06284600c684ed904d14c5c88ac".from_hex().unwrap();
//let script2 = Script::new(hex2);
//println!("1:\n{}", script);
//println!("2:\n{}", script2);
//assert!(false);
//}
}

View File

@ -1,6 +1,6 @@
use script::{Script, ScriptWitness};
pub struct SignatureData {
script: Script,
witness: ScriptWitness,
_script: Script,
_witness: ScriptWitness,
}

43
src/sign.rs Normal file
View File

@ -0,0 +1,43 @@
use script::Sighash;
use keys::KeyPair;
use transaction::{Transaction, TransactionOutput, MutableTransaction};
pub enum Error {
InvalidIndex,
InvalidPreviousOutputIndex,
}
pub fn sign_signature(
key: &KeyPair,
tx_from: &Transaction,
tx_to: &MutableTransaction,
index: usize,
hashtype: Sighash
) -> Result<Vec<u8>, Error> {
if index >= tx_to.transaction_inputs.len() {
return Err(Error::InvalidIndex);
}
let input = &tx_to.transaction_inputs[index];
let n = input.previous_output().index() as usize;
if n >= tx_from.transaction_outputs().len() {
return Err(Error::InvalidPreviousOutputIndex);
}
let output = &tx_from.transaction_outputs()[n];
sign_signature_with_output(key, output, tx_to, index, hashtype)
}
pub fn sign_signature_with_output(
_key: &KeyPair,
_output: &TransactionOutput,
tx: &MutableTransaction,
index: usize,
_hashtype: Sighash
) -> Result<Vec<u8>, Error> {
if index >= tx.transaction_inputs.len() {
return Err(Error::InvalidIndex);
}
unimplemented!();
}

View File

@ -41,6 +41,16 @@ impl Deserializable for OutPoint {
}
}
impl OutPoint {
pub fn hash(&self) -> &H256 {
&self.hash
}
pub fn index(&self) -> u32 {
self.index
}
}
#[derive(Debug)]
pub struct TransactionInput {
previous_output: OutPoint,
@ -75,6 +85,20 @@ impl Deserializable for TransactionInput {
}
}
impl TransactionInput {
pub fn previous_output(&self) -> &OutPoint {
&self.previous_output
}
pub fn script_sig(&self) -> &[u8] {
&self.script_sig
}
pub fn sequence(&self) -> u32 {
self.sequence
}
}
#[derive(Debug)]
pub struct TransactionOutput {
value: u64,
@ -159,6 +183,13 @@ impl Transaction {
}
}
pub struct MutableTransaction {
pub version: i32,
pub transaction_inputs: Vec<TransactionInput>,
pub transaction_outputs: Vec<TransactionOutput>,
pub lock_time: u32,
}
#[cfg(test)]
mod tests {
use hex::FromHex;