Skip to content

Commit f91e70c

Browse files
committed
Merge #212: Stop implementing elements::Encodable with bitcoin::Encodable
c08382c Copy ReadExt/WriteExt from bitcoin (Riccardo Casatta) 4aad862 Stop implementing elements::Encodable with bitcoin::Encodable (Riccardo Casatta) Pull request description: Following bitcoin versions change `io` with `bitcoin_io`, upgrading would then require changing also elements::Encodable to match. Instead, we are re-implementing what is needed. Makes #209 easier ACKs for top commit: apoelstra: ACK c08382c successfully ran local tests; a bit redundant but I think this is the right way to go Tree-SHA512: e849dc141ab412f1db3539a132688b28e2770befb8fc46e64d3396f16c3b9035bb7d76a0813d4d7bf65ff85df418cb42e8d75e01d1db7879c5853dd40214e053
2 parents f875ae2 + c08382c commit f91e70c

7 files changed

Lines changed: 403 additions & 81 deletions

File tree

src/block.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ use std::io;
2323
use crate::dynafed;
2424
use crate::hashes::{Hash, sha256};
2525
use crate::Transaction;
26-
use crate::encode::{self, Encodable, Decodable, serialize};
27-
use crate::{BlockHash, Script, TxMerkleNode, VarInt};
26+
use crate::encode::{self, serialize, Decodable, Encodable, VarInt};
27+
use crate::{BlockHash, Script, TxMerkleNode};
2828

2929
/// Data related to block signatures
3030
#[derive(Clone, Debug, Eq, Hash, PartialEq)]

src/encode.rs

Lines changed: 136 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
use std::io::Cursor;
1919
use std::{error, fmt, io, mem};
2020

21-
use bitcoin::consensus::encode as btcenc;
21+
use bitcoin::ScriptBuf;
2222
use secp256k1_zkp::{self, RangeProof, SurjectionProof, Tweak};
2323

2424
use crate::hashes::{sha256, Hash};
@@ -27,9 +27,6 @@ use crate::transaction::{Transaction, TxIn, TxOut};
2727

2828
pub use bitcoin::{self, consensus::encode::MAX_VEC_SIZE};
2929

30-
// Use the ReadExt/WriteExt traits as is from upstream
31-
pub use bitcoin::consensus::encode::{ReadExt, WriteExt};
32-
3330
use crate::taproot::TapLeafHash;
3431

3532
/// Encoding error
@@ -38,7 +35,7 @@ pub enum Error {
3835
/// And I/O error
3936
Io(io::Error),
4037
/// A Bitcoin encoding error.
41-
Bitcoin(btcenc::Error),
38+
Bitcoin(bitcoin::consensus::encode::Error),
4239
/// Tried to allocate an oversized vector
4340
OversizedVectorAllocation {
4441
/// The capacity requested
@@ -62,6 +59,8 @@ pub enum Error {
6259
HexError(crate::hex::Error),
6360
/// Got a time-based locktime when expecting a height-based one, or vice-versa
6461
BadLockTime(crate::LockTime),
62+
/// VarInt was encoded in a non-minimal way.
63+
NonMinimalVarInt,
6564
}
6665

6766
impl fmt::Display for Error {
@@ -87,23 +86,22 @@ impl fmt::Display for Error {
8786
Error::PsetError(ref e) => write!(f, "Pset Error: {}", e),
8887
Error::HexError(ref e) => write!(f, "Hex error {}", e),
8988
Error::BadLockTime(ref lt) => write!(f, "Invalid locktime {}", lt),
89+
Error::NonMinimalVarInt => write!(f, "non-minimal varint"),
9090
}
9191
}
9292
}
9393

9494
impl error::Error for Error {
9595
fn cause(&self) -> Option<&dyn error::Error> {
9696
match *self {
97-
Error::Bitcoin(ref e) => Some(e),
9897
Error::Secp256k1zkp(ref e) => Some(e),
9998
_ => None,
10099
}
101100
}
102101
}
103-
104102
#[doc(hidden)]
105-
impl From<btcenc::Error> for Error {
106-
fn from(e: btcenc::Error) -> Error {
103+
impl From<bitcoin::consensus::encode::Error> for Error {
104+
fn from(e: bitcoin::consensus::encode::Error) -> Error {
107105
Error::Bitcoin(e)
108106
}
109107
}
@@ -206,46 +204,15 @@ impl Decodable for sha256::Midstate {
206204
}
207205
}
208206

209-
pub(crate) fn consensus_encode_with_size<S: io::Write>(
207+
pub(crate) fn consensus_encode_with_size<S: crate::WriteExt>(
210208
data: &[u8],
211209
mut s: S,
212210
) -> Result<usize, Error> {
213-
let vi_len = bitcoin::VarInt(data.len() as u64).consensus_encode(&mut s)?;
211+
let vi_len = VarInt(data.len() as u64).consensus_encode(&mut s)?;
214212
s.emit_slice(data)?;
215213
Ok(vi_len + data.len())
216214
}
217215

218-
/// Implement Elements encodable traits for Bitcoin encodable types.
219-
macro_rules! impl_upstream {
220-
($type: ty) => {
221-
impl Encodable for $type {
222-
fn consensus_encode<W: io::Write>(&self, mut e: W) -> Result<usize, Error> {
223-
Ok(btcenc::Encodable::consensus_encode(self, &mut e)?)
224-
}
225-
}
226-
227-
impl Decodable for $type {
228-
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
229-
Ok(btcenc::Decodable::consensus_decode(&mut d)?)
230-
}
231-
}
232-
};
233-
}
234-
impl_upstream!(u8);
235-
impl_upstream!(u32);
236-
impl_upstream!(u64);
237-
impl_upstream!([u8; 4]);
238-
impl_upstream!([u8; 32]);
239-
impl_upstream!(Box<[u8]>);
240-
impl_upstream!([u8; 33]);
241-
impl_upstream!(Vec<u8>);
242-
impl_upstream!(Vec<Vec<u8>>);
243-
impl_upstream!(btcenc::VarInt);
244-
impl_upstream!(bitcoin::Transaction);
245-
impl_upstream!(bitcoin::BlockHash);
246-
impl_upstream!(bitcoin::ScriptBuf);
247-
impl_upstream!(crate::hashes::sha256d::Hash);
248-
249216
// Specific locktime types (which appear in PSET/PSBT2 but not in rust-bitcoin PSBT)
250217
impl Encodable for crate::locktime::Height {
251218
fn consensus_encode<S: io::Write>(&self, s: S) -> Result<usize, Error> {
@@ -275,14 +242,85 @@ impl Decodable for crate::locktime::Time {
275242
}
276243
}
277244

245+
/// A variable sized integer.
246+
pub struct VarInt(pub u64);
247+
impl Encodable for VarInt {
248+
fn consensus_encode<W: crate::WriteExt>(&self, mut e: W) -> Result<usize, Error> {
249+
Ok(e.emit_varint(self.0)?)
250+
}
251+
}
252+
impl Decodable for VarInt {
253+
fn consensus_decode<D: crate::ReadExt>(mut d: D) -> Result<Self, Error> {
254+
Ok(VarInt(d.read_varint()?))
255+
}
256+
}
257+
impl VarInt {
258+
/// returns the byte size used if this var int is serialized
259+
pub fn size(&self) -> usize {
260+
match self.0 {
261+
0..=0xFC => 1,
262+
0xFD..=0xFFFF => 3,
263+
0x10000..=0xFFFFFFFF => 5,
264+
_ => 9,
265+
}
266+
}
267+
}
268+
269+
// Primitive types
270+
macro_rules! impl_int {
271+
($ty:ident, $meth_dec:ident, $meth_enc:ident) => {
272+
impl Encodable for $ty {
273+
fn consensus_encode<W: crate::WriteExt>(&self, mut w: W) -> Result<usize, Error> {
274+
w.$meth_enc(*self)?;
275+
Ok(mem::size_of::<$ty>())
276+
}
277+
}
278+
impl Decodable for $ty {
279+
fn consensus_decode<R: crate::ReadExt>(mut r: R) -> Result<Self, Error> {
280+
crate::ReadExt::$meth_dec(&mut r)
281+
}
282+
}
283+
};
284+
}
285+
286+
impl_int!(u8, read_u8, emit_u8);
287+
impl_int!(u16, read_u16, emit_u16);
288+
impl_int!(u32, read_u32, emit_u32);
289+
impl_int!(u64, read_u64, emit_u64);
290+
291+
impl Encodable for bitcoin::ScriptBuf {
292+
fn consensus_encode<W: io::Write>(&self, w: W) -> Result<usize, Error> {
293+
consensus_encode_with_size(self.as_script().as_bytes(), w)
294+
}
295+
}
296+
impl Decodable for bitcoin::ScriptBuf {
297+
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, Error> {
298+
let bytes = Vec::<u8>::consensus_decode(d)?;
299+
Ok(ScriptBuf::from_bytes(bytes))
300+
}
301+
}
302+
303+
impl Encodable for bitcoin::hashes::sha256d::Hash {
304+
fn consensus_encode<W: io::Write>(&self, mut w: W) -> Result<usize, Error> {
305+
self.as_byte_array().consensus_encode(&mut w)
306+
}
307+
}
308+
impl Decodable for bitcoin::hashes::sha256d::Hash {
309+
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, Error> {
310+
Ok(Self::from_byte_array(
311+
<<Self as Hash>::Bytes>::consensus_decode(d)?,
312+
))
313+
}
314+
}
315+
278316
// Vectors
279317
macro_rules! impl_vec {
280318
($type: ty) => {
281319
impl Encodable for Vec<$type> {
282320
#[inline]
283321
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, Error> {
284322
let mut len = 0;
285-
len += btcenc::VarInt(self.len() as u64).consensus_encode(&mut s)?;
323+
len += VarInt(self.len() as u64).consensus_encode(&mut s)?;
286324
for c in self.iter() {
287325
len += c.consensus_encode(&mut s)?;
288326
}
@@ -293,7 +331,7 @@ macro_rules! impl_vec {
293331
impl Decodable for Vec<$type> {
294332
#[inline]
295333
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
296-
let len = btcenc::VarInt::consensus_decode(&mut d)?.0;
334+
let len = VarInt::consensus_decode(&mut d)?.0;
297335
let byte_size = (len as usize)
298336
.checked_mul(mem::size_of::<$type>())
299337
.ok_or(self::Error::ParseFailed("Invalid length"))?;
@@ -316,6 +354,60 @@ impl_vec!(TxIn);
316354
impl_vec!(TxOut);
317355
impl_vec!(Transaction);
318356
impl_vec!(TapLeafHash);
357+
impl_vec!(Vec<u8>); // Vec<Vec<u8>>
358+
359+
macro_rules! impl_array {
360+
( $size:literal ) => {
361+
impl Encodable for [u8; $size] {
362+
#[inline]
363+
fn consensus_encode<W: crate::WriteExt>(
364+
&self,
365+
mut w: W,
366+
) -> core::result::Result<usize, Error> {
367+
w.emit_slice(&self[..])?;
368+
Ok($size)
369+
}
370+
}
371+
372+
impl Decodable for [u8; $size] {
373+
#[inline]
374+
fn consensus_decode<R: crate::ReadExt>(mut r: R) -> core::result::Result<Self, Error> {
375+
let mut ret = [0; $size];
376+
r.read_slice(&mut ret)?;
377+
Ok(ret)
378+
}
379+
}
380+
};
381+
}
382+
impl_array!(4);
383+
impl_array!(32);
384+
impl_array!(33);
385+
386+
impl Encodable for Box<[u8]> {
387+
fn consensus_encode<W: io::Write>(&self, mut w: W) -> Result<usize, Error> {
388+
consensus_encode_with_size(&self[..], &mut w)
389+
}
390+
}
391+
impl Decodable for Box<[u8]> {
392+
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, Error> {
393+
let v = Vec::<u8>::consensus_decode(d)?;
394+
Ok(v.into())
395+
}
396+
}
397+
398+
impl Encodable for Vec<u8> {
399+
fn consensus_encode<W: io::Write>(&self, mut w: W) -> Result<usize, Error> {
400+
consensus_encode_with_size(&self[..], &mut w)
401+
}
402+
}
403+
impl Decodable for Vec<u8> {
404+
fn consensus_decode<D: crate::ReadExt>(mut d: D) -> Result<Self, Error> {
405+
let s = VarInt::consensus_decode(&mut d)?.0 as usize;
406+
let mut v = vec![0; s];
407+
d.read_slice(&mut v)?;
408+
Ok(v)
409+
}
410+
}
319411

320412
macro_rules! impl_box_option {
321413
($type: ty) => {

0 commit comments

Comments
 (0)