extern crate hex;
extern crate sha2;
mod sighash;
mod buffer;
pub mod op;
use sha2::{Sha256, Digest};
use buffer::{ByteBuffer};
pub fn get_var_int(value: usize) -> Vec<u8> {
let mut data: Vec<u8> = vec![];
if value > 0xFFFFFFFF {
data.push(0xFF);
data.append(&mut (value as u64).to_le_bytes().to_vec());
}
else if value > 0xFFFF {
data.push(0xFE);
data.append(&mut (value as u32).to_le_bytes().to_vec());
}
else if value > 0xFC {
data.push(0xFD);
data.append(&mut (value as u16).to_le_bytes().to_vec());
}
else {
data.append(&mut (value as u8).to_le_bytes().to_vec());
}
return data;
}
#[derive(Clone)]
pub struct TxIn {
prev_hash: Vec<u8>,
prev_out: u32,
script_sig: Vec<u8>,
seq_no: u32,
}
impl TxIn {
pub fn deserialize(buffer: &mut ByteBuffer) -> TxIn {
let mut txin = TxIn{
prev_hash: vec![],
prev_out: 0,
script_sig: vec![],
seq_no: 0,
};
txin.prev_hash = buffer.read_bytes(32);
txin.prev_out = buffer.read_u32();
let script_len = buffer.read_var_int() as usize;
txin.script_sig = buffer.read_bytes(script_len);
txin.seq_no = buffer.read_u32();
return txin;
}
pub fn serialize(&self) -> Vec<u8> {
let mut data = vec![];
data.extend(self.prev_hash.as_slice());
data.extend(self.prev_out.to_le_bytes().to_vec());
data.extend(get_var_int(self.script_sig.len()));
data.extend(self.script_sig.as_slice());
data.extend(self.seq_no.to_le_bytes().to_vec());
return data;
}
}
#[derive(Clone)]
pub struct TxOut {
value: u64,
script_pub_key: Vec<u8>,
}
impl TxOut {
pub fn deserialize(buffer: &mut ByteBuffer) -> TxOut {
let mut txout = TxOut{
value: 0,
script_pub_key: vec![],
};
txout.value = buffer.read_u64();
let script_len = buffer.read_var_int() as usize;
txout.script_pub_key = buffer.read_bytes(script_len);
return txout;
}
pub fn serialize(&self) -> Vec<u8> {
let mut data = vec![];
data.extend(self.value.to_le_bytes().to_vec());
data.extend(get_var_int(self.script_pub_key.len()));
data.extend(self.script_pub_key.as_slice());
return data;
}
}
#[derive(Clone)]
pub struct Tx {
version: u32,
inputs: Vec<TxIn>,
outputs: Vec<TxOut>,
lock_time: u32,
}
impl Tx {
pub fn deserialize(data: Vec<u8>) -> Tx {
let mut buffer = ByteBuffer::from_vec(data);
let mut tx = Tx {
version: 0,
inputs: vec![],
outputs: vec![],
lock_time: 0,
};
tx.version = buffer.read_u32();
let inp_count = buffer.read_var_int();
for _ in 0..inp_count {
tx.inputs.push(TxIn::deserialize(&mut buffer));
}
let out_count = buffer.read_var_int();
for _ in 0..out_count {
tx.outputs.push(TxOut::deserialize(&mut buffer));
}
tx.lock_time = buffer.read_u32();
return tx;
}
pub fn serialize(&self) -> Vec<u8> {
let mut data = vec![];
data.extend(self.version.to_le_bytes().to_vec());
data.extend(get_var_int(self.inputs.len()));
for inp in &self.inputs {
data.extend(inp.serialize());
}
data.extend(get_var_int(self.outputs.len()));
for out in &self.outputs {
data.extend(out.serialize());
}
data.extend(self.lock_time.to_le_bytes().to_vec());
return data;
}
pub fn sighash_serialize(&self, sighash_type: u8, index: usize, pubkey: Vec<u8>) -> Result<Vec<u8>, &'static str> {
if (sighash_type & sighash::FORKID) == 0 {
return Err("Sighash forkID must be set, this is Bitcoin SV");
}
let mut tmp = self.clone();
for inp in &mut tmp.inputs {
inp.script_sig = vec![];
}
if index > tmp.inputs.len() {
return Err("Index too large for inputs");
}
tmp.inputs[index].script_sig = pubkey;
let lower_sighash_bits = sighash_type & 0x1F;
match lower_sighash_bits {
sighash::NONE | sighash::SINGLE => {
for i in 0..tmp.inputs.len() {
if i != index {
tmp.inputs[i].seq_no = 0;
}
}
match lower_sighash_bits {
sighash::NONE => {
tmp.outputs = vec![];
}
sighash::SINGLE => {
if index > tmp.outputs.len() {
return Err("Index too large for outputs");
}
let out = tmp.outputs[index].clone();
tmp.outputs = vec![out];
}
_ => {}
}
}
_ => {
return Err("Invalid, sighash type unknown");
}
}
if (sighash_type & sighash::ANYONECANPAY) != 0 {
let inp = tmp.inputs[index].clone();
tmp.inputs = vec![inp];
}
let mut result = vec![];
result.extend(tmp.serialize());
result.push(sighash_type);
return Ok(result);
}
pub fn sighash(&self, sighash_type: u8, index: usize, pubkey: Vec<u8>) -> Result<Vec<u8>, &'static str> {
match self.sighash_serialize(sighash_type, index, pubkey) {
Ok(serialized) => {
Sha256::digest(serialized.as_slice());
return Ok(Sha256::digest(serialized.as_slice()).to_vec());
}
Err(err) => {
return Err(err);
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use hex;
#[test]
fn serialization_test() {
let tx1 = "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a01ff47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000";
let want = hex::decode(tx1).unwrap();
let got = Tx::deserialize(want.clone())
.serialize();
println!("{:?}", want);
println!("{:?}", got);
if want.len() != got.len() {
panic!("bad sized serialized vector got={}, want={}", got.len(), want.len());
}
want.iter().enumerate().zip(got.iter())
.for_each(|((wi, w), g)| {
if w != g {
println!("Looking at index {}", wi);
assert_eq!(w,g, "Not all bytes are equal from serialization");
}
});
}
}