chore(primitives): revise signature interface and transaction encode (#928)

Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>
This commit is contained in:
Kim, JinSan
2023-01-23 05:53:32 +09:00
committed by GitHub
parent d32710e1ea
commit 1e84189fec
2 changed files with 193 additions and 227 deletions

View File

@@ -269,25 +269,6 @@ impl Transaction {
}
}
/// Encodes individual transaction fields into the desired buffer, without a RLP header.
pub(crate) fn encode_inner(&self, out: &mut dyn bytes::BufMut) {
match self {
Transaction::Legacy { .. } => self.encode_fields(out),
Transaction::Eip2930 { .. } => {
out.put_u8(1);
let list_header = Header { list: true, payload_length: self.fields_len() };
list_header.encode(out);
self.encode_fields(out);
}
Transaction::Eip1559 { .. } => {
out.put_u8(2);
let list_header = Header { list: true, payload_length: self.fields_len() };
list_header.encode(out);
self.encode_fields(out);
}
}
}
/// Encodes EIP-155 arguments into the desired buffer. Only encodes values for legacy
/// transactions.
pub(crate) fn encode_eip155_fields(&self, out: &mut dyn bytes::BufMut) {
@@ -315,21 +296,6 @@ impl Transaction {
}
}
/// Outputs the length of the transaction payload without the length of the RLP header or
/// eip155 fields.
pub(crate) fn payload_len(&self) -> usize {
match self {
Transaction::Legacy { .. } => self.fields_len(),
_ => {
let mut len = self.fields_len();
// add list header length
len += length_of_length(len);
// add transaction type byte length
len + 1
}
}
}
/// Outputs the length of the transaction's fields, without a RLP header or length of the
/// eip155 fields.
pub(crate) fn fields_len(&self) -> usize {
@@ -466,26 +432,32 @@ impl Transaction {
/// intended for signing.
impl Encodable for Transaction {
fn length(&self) -> usize {
// TODO: fix
let len = self.payload_len();
len + length_of_length(len)
match self {
Transaction::Legacy { .. } => {
let payload_length = self.fields_len() + self.eip155_fields_len();
// 'header length' + 'payload length'
length_of_length(payload_length) + payload_length
}
_ => {
let payload_length = self.fields_len();
// 'transaction type byte length' + 'header length' + 'payload length'
1 + length_of_length(payload_length) + payload_length
}
}
}
fn encode(&self, out: &mut dyn bytes::BufMut) {
match self {
Transaction::Legacy { .. } => {
let header = Header {
list: true,
payload_length: self.payload_len() + self.eip155_fields_len(),
};
header.encode(out);
self.encode_inner(out);
Header { list: true, payload_length: self.fields_len() + self.eip155_fields_len() }
.encode(out);
self.encode_fields(out);
self.encode_eip155_fields(out);
}
Transaction::Eip2930 { .. } => {
self.encode_inner(out);
}
Transaction::Eip1559 { .. } => {
self.encode_inner(out);
_ => {
out.put_u8(self.tx_type() as u8);
Header { list: true, payload_length: self.fields_len() }.encode(out);
self.encode_fields(out);
}
}
}
@@ -607,10 +579,7 @@ impl Encodable for TransactionSigned {
}
fn length(&self) -> usize {
let len = self.payload_len();
// add the length of the RLP header
len + length_of_length(len)
self.payload_len_inner()
}
}
@@ -661,11 +630,7 @@ impl Decodable for TransactionSigned {
_ => return Err(DecodeError::Custom("unsupported typed transaction type")),
};
let signature = Signature {
odd_y_parity: Decodable::decode(buf)?,
r: Decodable::decode(buf)?,
s: Decodable::decode(buf)?,
};
let signature = Signature::decode(buf)?;
let hash = keccak256(&original_encoding[..first_header.payload_length]);
let signed = TransactionSigned { transaction, hash, signature };
@@ -680,7 +645,7 @@ impl Decodable for TransactionSigned {
input: Bytes(Decodable::decode(buf)?),
chain_id: None,
});
let (signature, extracted_id) = Signature::decode_eip155_inner(buf)?;
let (signature, extracted_id) = Signature::decode_with_eip155_chain_id(buf)?;
if let Some(id) = extracted_id {
transaction.set_chain_id(id);
}
@@ -727,42 +692,50 @@ impl TransactionSigned {
/// Inner encoding function that is used for both rlp [`Encodable`] trait and for calculating
/// hash that for eip2728 does not require rlp header
pub(crate) fn encode_inner(&self, out: &mut dyn bytes::BufMut, with_header: bool) {
if let Transaction::Legacy(TxLegacy { chain_id, .. }) = self.transaction {
let header = Header { list: true, payload_length: self.payload_len() };
header.encode(out);
self.transaction.encode_fields(out);
if let Some(id) = chain_id {
self.signature.encode_eip155_inner(out, id);
} else {
// if the transaction has no chain id then it is a pre-EIP-155 transaction
self.signature.encode_inner_legacy(out);
}
} else {
if with_header {
let header = Header { list: false, payload_length: self.payload_len() };
match self.transaction {
Transaction::Legacy(TxLegacy { chain_id, .. }) => {
// do nothing w/ with_header
let payload_length = self.transaction.fields_len() +
self.signature.payload_len_with_eip155_chain_id(chain_id);
let header = Header { list: true, payload_length };
header.encode(out);
self.transaction.encode_fields(out);
self.signature.encode_with_eip155_chain_id(out, chain_id);
}
match self.transaction {
Transaction::Eip2930 { .. } => {
out.put_u8(1);
let list_header = Header { list: true, payload_length: self.inner_tx_len() };
list_header.encode(out);
}
Transaction::Eip1559 { .. } => {
out.put_u8(2);
let list_header = Header { list: true, payload_length: self.inner_tx_len() };
list_header.encode(out);
}
Transaction::Legacy { .. } => {
unreachable!("Legacy transaction should be handled above")
_ => {
let payload_length = self.transaction.fields_len() + self.signature.payload_len();
if with_header {
Header {
list: false,
payload_length: 1 + length_of_length(payload_length) + payload_length,
}
.encode(out);
}
out.put_u8(self.transaction.tx_type() as u8);
let header = Header { list: true, payload_length };
header.encode(out);
self.transaction.encode_fields(out);
self.signature.encode(out);
}
}
}
self.transaction.encode_fields(out);
self.signature.odd_y_parity.encode(out);
self.signature.r.encode(out);
self.signature.s.encode(out);
/// Output the length of the encode_inner(out, true). Note to assume that `with_header` is only
/// `true`.
pub(crate) fn payload_len_inner(&self) -> usize {
match self.transaction {
Transaction::Legacy(TxLegacy { chain_id, .. }) => {
let payload_length = self.transaction.fields_len() +
self.signature.payload_len_with_eip155_chain_id(chain_id);
// 'header length' + 'payload length'
length_of_length(payload_length) + payload_length
}
_ => {
let payload_length = self.transaction.fields_len() + self.signature.payload_len();
// 'transaction type byte length' + 'header length' + 'payload length'
let len = 1 + length_of_length(payload_length) + payload_length;
length_of_length(len) + len
}
}
}
@@ -781,37 +754,6 @@ impl TransactionSigned {
initial_tx.hash = initial_tx.recalculate_hash();
initial_tx
}
/// Output the length of the inner transaction and signature fields.
pub(crate) fn inner_tx_len(&self) -> usize {
let mut len = self.transaction.fields_len();
if let Transaction::Legacy(TxLegacy { chain_id, .. }) = self.transaction {
if let Some(id) = chain_id {
len += self.signature.eip155_payload_len(id);
} else {
// if the transaction has no chain id then it is a pre-EIP-155 transaction
len += self.signature.payload_len_legacy();
}
} else {
len += self.signature.odd_y_parity.length();
len += self.signature.r.length();
len += self.signature.s.length();
}
len
}
/// Output the length of the signed transaction's rlp payload without a rlp header.
pub(crate) fn payload_len(&self) -> usize {
let mut len = self.inner_tx_len();
if let Transaction::Legacy { .. } = self.transaction {
len
} else {
// length of the list header
len += Header { list: true, payload_length: len }.length();
// add type byte
len + 1
}
}
}
/// Signed transaction with recovered signer.
@@ -923,6 +865,7 @@ mod tests {
let mut encoded = BytesMut::new();
tx.encode(&mut encoded);
assert_eq!(encoded.len(), tx.length());
let decoded = TransactionSigned::decode(&mut &*encoded).unwrap();
assert_eq!(decoded, tx);
@@ -934,7 +877,14 @@ mod tests {
let tx_bytes =
hex::decode("b901f202f901ee05228459682f008459682f11830209bf8080b90195608060405234801561001057600080fd5b50610175806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80630c49c36c14610030575b600080fd5b61003861004e565b604051610045919061011d565b60405180910390f35b60606020600052600f6020527f68656c6c6f2073746174656d696e64000000000000000000000000000000000060405260406000f35b600081519050919050565b600082825260208201905092915050565b60005b838110156100be5780820151818401526020810190506100a3565b838111156100cd576000848401525b50505050565b6000601f19601f8301169050919050565b60006100ef82610084565b6100f9818561008f565b93506101098185602086016100a0565b610112816100d3565b840191505092915050565b6000602082019050818103600083015261013781846100e4565b90509291505056fea264697066735822122051449585839a4ea5ac23cae4552ef8a96b64ff59d0668f76bfac3796b2bdbb3664736f6c63430008090033c080a0136ebffaa8fc8b9fda9124de9ccb0b1f64e90fbd44251b4c4ac2501e60b104f9a07eb2999eec6d185ef57e91ed099afb0a926c5b536f0155dd67e537c7476e1471")
.unwrap();
let _decoded = TransactionSigned::decode(&mut &tx_bytes[..]).unwrap();
let decoded = TransactionSigned::decode(&mut &tx_bytes[..]).unwrap();
assert_eq!(tx_bytes.len(), decoded.length());
let mut encoded = BytesMut::new();
decoded.encode(&mut encoded);
assert_eq!(tx_bytes, encoded);
}
#[test]
@@ -956,6 +906,7 @@ mod tests {
let mut encoded = BytesMut::new();
tx.encode(&mut encoded);
assert_eq!(encoded.len(), tx.length());
let decoded = TransactionSigned::decode(&mut &*encoded).unwrap();
assert_eq!(decoded, tx);
@@ -975,8 +926,8 @@ mod tests {
#[test]
fn decode_multiple_network_txs() {
let bytes_first = &mut &hex::decode("f86b02843b9aca00830186a094d3e8763675e4c425df46cc3b5c0f6cbdac39604687038d7ea4c68000802ba00eb96ca19e8a77102767a41fc85a36afd5c61ccb09911cec5d3e86e193d9c5aea03a456401896b1b6055311536bf00a718568c744d8c1f9df59879e8350220ca18").unwrap()[..];
let expected_request = Transaction::Legacy(TxLegacy {
let bytes = hex::decode("f86b02843b9aca00830186a094d3e8763675e4c425df46cc3b5c0f6cbdac39604687038d7ea4c68000802ba00eb96ca19e8a77102767a41fc85a36afd5c61ccb09911cec5d3e86e193d9c5aea03a456401896b1b6055311536bf00a718568c744d8c1f9df59879e8350220ca18").unwrap();
let transaction = Transaction::Legacy(TxLegacy {
chain_id: Some(4u64),
nonce: 2,
gas_price: 1000000000,
@@ -987,24 +938,20 @@ mod tests {
value: 1000000000000000,
input: Bytes::default(),
});
let expected_signature = Signature {
let signature = Signature {
odd_y_parity: false,
r: U256::from_str("0xeb96ca19e8a77102767a41fc85a36afd5c61ccb09911cec5d3e86e193d9c5ae")
.unwrap(),
s: U256::from_str("0x3a456401896b1b6055311536bf00a718568c744d8c1f9df59879e8350220ca18")
.unwrap(),
};
let expected =
TransactionSigned::from_transaction_and_signature(expected_request, expected_signature);
assert_eq!(expected, TransactionSigned::decode(bytes_first).unwrap());
assert_eq!(
expected.hash,
let hash =
H256::from_str("0xa517b206d2223278f860ea017d3626cacad4f52ff51030dc9a96b432f17f8d34")
.unwrap()
);
.ok();
test_decode_and_encode(bytes, transaction, signature, hash);
let bytes_second = &mut &hex::decode("f86b01843b9aca00830186a094d3e8763675e4c425df46cc3b5c0f6cbdac3960468702769bb01b2a00802ba0e24d8bd32ad906d6f8b8d7741e08d1959df021698b19ee232feba15361587d0aa05406ad177223213df262cb66ccbb2f46bfdccfdfbbb5ffdda9e2c02d977631da").unwrap()[..];
let expected_request = Transaction::Legacy(TxLegacy {
let bytes = hex::decode("f86b01843b9aca00830186a094d3e8763675e4c425df46cc3b5c0f6cbdac3960468702769bb01b2a00802ba0e24d8bd32ad906d6f8b8d7741e08d1959df021698b19ee232feba15361587d0aa05406ad177223213df262cb66ccbb2f46bfdccfdfbbb5ffdda9e2c02d977631da").unwrap();
let transaction = Transaction::Legacy(TxLegacy {
chain_id: Some(4),
nonce: 1u64,
gas_price: 1000000000,
@@ -1015,20 +962,17 @@ mod tests {
value: 693361000000000u64.into(),
input: Default::default(),
});
let expected_signature = Signature {
let signature = Signature {
odd_y_parity: false,
r: U256::from_str("0xe24d8bd32ad906d6f8b8d7741e08d1959df021698b19ee232feba15361587d0a")
.unwrap(),
s: U256::from_str("0x5406ad177223213df262cb66ccbb2f46bfdccfdfbbb5ffdda9e2c02d977631da")
.unwrap(),
};
test_decode_and_encode(bytes, transaction, signature, None);
let expected =
TransactionSigned::from_transaction_and_signature(expected_request, expected_signature);
assert_eq!(expected, TransactionSigned::decode(bytes_second).unwrap());
let bytes_third = &mut &hex::decode("f86b0384773594008398968094d3e8763675e4c425df46cc3b5c0f6cbdac39604687038d7ea4c68000802ba0ce6834447c0a4193c40382e6c57ae33b241379c5418caac9cdc18d786fd12071a03ca3ae86580e94550d7c071e3a02eadb5a77830947c9225165cf9100901bee88").unwrap()[..];
let expected_request = Transaction::Legacy(TxLegacy {
let bytes = hex::decode("f86b0384773594008398968094d3e8763675e4c425df46cc3b5c0f6cbdac39604687038d7ea4c68000802ba0ce6834447c0a4193c40382e6c57ae33b241379c5418caac9cdc18d786fd12071a03ca3ae86580e94550d7c071e3a02eadb5a77830947c9225165cf9100901bee88").unwrap();
let transaction = Transaction::Legacy(TxLegacy {
chain_id: Some(4),
nonce: 3,
gas_price: 2000000000,
@@ -1039,21 +983,17 @@ mod tests {
value: 1000000000000000u64.into(),
input: Bytes::default(),
});
let expected_signature = Signature {
let signature = Signature {
odd_y_parity: false,
r: U256::from_str("0xce6834447c0a4193c40382e6c57ae33b241379c5418caac9cdc18d786fd12071")
.unwrap(),
s: U256::from_str("0x3ca3ae86580e94550d7c071e3a02eadb5a77830947c9225165cf9100901bee88")
.unwrap(),
};
test_decode_and_encode(bytes, transaction, signature, None);
let expected =
TransactionSigned::from_transaction_and_signature(expected_request, expected_signature);
assert_eq!(expected, TransactionSigned::decode(bytes_third).unwrap());
let bytes_fourth = &mut &hex::decode("b87502f872041a8459682f008459682f0d8252089461815774383099e24810ab832a5b2a5425c154d58829a2241af62c000080c001a059e6b67f48fb32e7e570dfb11e042b5ad2e55e3ce3ce9cd989c7e06e07feeafda0016b83f4f980694ed2eee4d10667242b1f40dc406901b34125b008d334d47469").unwrap()[..];
let expected = Transaction::Eip1559(TxEip1559 {
let bytes = hex::decode("b87502f872041a8459682f008459682f0d8252089461815774383099e24810ab832a5b2a5425c154d58829a2241af62c000080c001a059e6b67f48fb32e7e570dfb11e042b5ad2e55e3ce3ce9cd989c7e06e07feeafda0016b83f4f980694ed2eee4d10667242b1f40dc406901b34125b008d334d47469").unwrap();
let transaction = Transaction::Eip1559(TxEip1559 {
chain_id: 4,
nonce: 26,
max_priority_fee_per_gas: 1500000000,
@@ -1066,21 +1006,17 @@ mod tests {
input: Default::default(),
access_list: Default::default(),
});
let expected_signature = Signature {
let signature = Signature {
odd_y_parity: true,
r: U256::from_str("0x59e6b67f48fb32e7e570dfb11e042b5ad2e55e3ce3ce9cd989c7e06e07feeafd")
.unwrap(),
s: U256::from_str("0x016b83f4f980694ed2eee4d10667242b1f40dc406901b34125b008d334d47469")
.unwrap(),
};
test_decode_and_encode(bytes, transaction, signature, None);
let expected =
TransactionSigned::from_transaction_and_signature(expected, expected_signature);
assert_eq!(expected, TransactionSigned::decode(bytes_fourth).unwrap());
let bytes_fifth = &mut &hex::decode("f8650f84832156008287fb94cf7f9e66af820a19257a2108375b180b0ec491678204d2802ca035b7bfeb9ad9ece2cbafaaf8e202e706b4cfaeb233f46198f00b44d4a566a981a0612638fb29427ca33b9a3be2a0a561beecfe0269655be160d35e72d366a6a860").unwrap()[..];
let expected = Transaction::Legacy(TxLegacy {
let bytes = hex::decode("f8650f84832156008287fb94cf7f9e66af820a19257a2108375b180b0ec491678204d2802ca035b7bfeb9ad9ece2cbafaaf8e202e706b4cfaeb233f46198f00b44d4a566a981a0612638fb29427ca33b9a3be2a0a561beecfe0269655be160d35e72d366a6a860").unwrap();
let transaction = Transaction::Legacy(TxLegacy {
chain_id: Some(4),
nonce: 15,
gas_price: 2200000000,
@@ -1098,9 +1034,27 @@ mod tests {
s: U256::from_str("0x612638fb29427ca33b9a3be2a0a561beecfe0269655be160d35e72d366a6a860")
.unwrap(),
};
test_decode_and_encode(bytes, transaction, signature, None);
}
let expected = TransactionSigned::from_transaction_and_signature(expected, signature);
assert_eq!(expected, TransactionSigned::decode(bytes_fifth).unwrap());
fn test_decode_and_encode(
bytes: Vec<u8>,
transaction: Transaction,
signature: Signature,
hash: Option<H256>,
) {
let expected = TransactionSigned::from_transaction_and_signature(transaction, signature);
if let Some(hash) = hash {
assert_eq!(hash, expected.hash);
}
assert_eq!(bytes.len(), expected.length());
let decoded = TransactionSigned::decode(&mut &bytes[..]).unwrap();
assert_eq!(expected, decoded);
let mut encoded = BytesMut::new();
expected.encode(&mut encoded);
assert_eq!(bytes, encoded);
}
#[test]

View File

@@ -17,41 +17,40 @@ pub struct Signature {
}
impl Signature {
/// Encode the `v`, `r`, `s` values without a RLP header.
/// Encodes the `v` value using the legacy scheme without EIP-155.
pub(crate) fn encode_inner_legacy(&self, out: &mut dyn reth_rlp::BufMut) {
(self.odd_y_parity as u8 + 27).encode(out);
self.r.encode(out);
self.s.encode(out);
}
/// Output the length of the signature without the length of the RLP header, using the legacy
/// scheme without EIP-155.
pub(crate) fn payload_len_legacy(&self) -> usize {
(self.odd_y_parity as u8 + 27).length() + self.r.length() + self.s.length()
/// scheme with EIP-155 support depends on chain_id.
pub(crate) fn payload_len_with_eip155_chain_id(&self, chain_id: Option<u64>) -> usize {
self.v(chain_id).length() + self.r.length() + self.s.length()
}
/// Encode the `v`, `r`, `s` values without a RLP header.
/// Encodes the `v` value with EIP-155 support, using the specified chain ID.
pub(crate) fn encode_eip155_inner(&self, out: &mut dyn reth_rlp::BufMut, chain_id: u64) {
// EIP-155: v = {0, 1} + CHAIN_ID * 2 + 35
let v = chain_id * 2 + 35 + self.odd_y_parity as u64;
v.encode(out);
/// Encodes the `v` value using the legacy scheme with EIP-155 support depends on chain_id.
pub(crate) fn encode_with_eip155_chain_id(
&self,
out: &mut dyn reth_rlp::BufMut,
chain_id: Option<u64>,
) {
self.v(chain_id).encode(out);
self.r.encode(out);
self.s.encode(out);
}
/// Output the length of the signature without the length of the RLP header, with EIP-155
/// support.
pub(crate) fn eip155_payload_len(&self, chain_id: u64) -> usize {
// EIP-155: v = {0, 1} + CHAIN_ID * 2 + 35
let v = chain_id * 2 + 35 + self.odd_y_parity as u64;
v.length() + self.r.length() + self.s.length()
/// Output the `v` of the signature depends on chain_id
#[inline]
fn v(&self, chain_id: Option<u64>) -> u64 {
if let Some(chain_id) = chain_id {
// EIP-155: v = {0, 1} + CHAIN_ID * 2 + 35
self.odd_y_parity as u64 + chain_id * 2 + 35
} else {
self.odd_y_parity as u64 + 27
}
}
/// Decodes the `v`, `r`, `s` values without a RLP header.
/// This will return a chain ID if the `v` value is EIP-155 compatible.
pub(crate) fn decode_eip155_inner(buf: &mut &[u8]) -> Result<(Self, Option<u64>), DecodeError> {
pub(crate) fn decode_with_eip155_chain_id(
buf: &mut &[u8],
) -> Result<(Self, Option<u64>), DecodeError> {
let v = u64::decode(buf)?;
let r = Decodable::decode(buf)?;
let s = Decodable::decode(buf)?;
@@ -67,6 +66,27 @@ impl Signature {
}
}
/// Output the length of the signature without the length of the RLP header
pub(crate) fn payload_len(&self) -> usize {
self.odd_y_parity.length() + self.r.length() + self.s.length()
}
/// Encode the `odd_y_parity`, `r`, `s` values without a RLP header.
pub(crate) fn encode(&self, out: &mut dyn reth_rlp::BufMut) {
self.odd_y_parity.encode(out);
self.r.encode(out);
self.s.encode(out);
}
/// Decodes the `odd_y_parity`, `r`, `s` values without a RLP header.
pub(crate) fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
Ok(Signature {
odd_y_parity: Decodable::decode(buf)?,
r: Decodable::decode(buf)?,
s: Decodable::decode(buf)?,
})
}
/// Recover signature from hash.
pub(crate) fn recover_signer(&self, hash: H256) -> Option<Address> {
let mut sig: [u8; 65] = [0; 65];
@@ -90,69 +110,61 @@ mod tests {
use crate::{Address, Signature, H256, U256};
#[test]
fn test_encode_inner_legacy() {
fn test_payload_len_with_eip155_chain_id() {
let signature = Signature { r: U256::default(), s: U256::default(), odd_y_parity: false };
let mut encoded = BytesMut::new();
signature.encode_inner_legacy(&mut encoded);
let expected = 27u8;
assert_eq!(expected, encoded.as_ref()[0]);
assert_eq!(3, signature.payload_len_with_eip155_chain_id(None));
assert_eq!(3, signature.payload_len_with_eip155_chain_id(Some(1)));
assert_eq!(4, signature.payload_len_with_eip155_chain_id(Some(47)));
}
#[test]
fn test_v() {
let signature = Signature { r: U256::default(), s: U256::default(), odd_y_parity: false };
assert_eq!(27, signature.v(None));
assert_eq!(37, signature.v(Some(1)));
let signature = Signature { r: U256::default(), s: U256::default(), odd_y_parity: true };
let mut encoded = BytesMut::new();
signature.encode_inner_legacy(&mut encoded);
let expected = 28u8;
assert_eq!(expected, encoded.as_ref()[0]);
assert_eq!(28, signature.v(None));
assert_eq!(38, signature.v(Some(1)));
}
#[test]
fn test_payload_len_legacy() {
let signature = Signature { r: U256::default(), s: U256::default(), odd_y_parity: false };
let len = signature.payload_len_legacy();
assert_eq!(3, len);
}
#[test]
fn test_encode_eip155_inner() {
let signature = Signature { r: U256::default(), s: U256::default(), odd_y_parity: false };
let mut encoded = BytesMut::new();
signature.encode_eip155_inner(&mut encoded, 1);
let expected = 37u8;
assert_eq!(expected, encoded.as_ref()[0]);
let signature = Signature { r: U256::default(), s: U256::default(), odd_y_parity: true };
let mut encoded = BytesMut::new();
signature.encode_eip155_inner(&mut encoded, 1);
let expected = 38u8;
assert_eq!(expected, encoded.as_ref()[0]);
}
#[test]
fn test_eip155_payload_len() {
let signature = Signature { r: U256::default(), s: U256::default(), odd_y_parity: false };
let len = signature.eip155_payload_len(1);
assert_eq!(3, len);
let len = signature.eip155_payload_len(47);
assert_eq!(4, len);
}
#[test]
fn test_decode_eip155_inner() {
fn test_encode_and_decode_with_eip155_chain_id() {
let signature = Signature { r: U256::default(), s: U256::default(), odd_y_parity: false };
let mut encoded = BytesMut::new();
signature.encode_inner_legacy(&mut encoded);
let (decoded, chain_id) = Signature::decode_eip155_inner(&mut &*encoded).unwrap();
signature.encode_with_eip155_chain_id(&mut encoded, None);
assert_eq!(encoded.len(), signature.payload_len_with_eip155_chain_id(None));
let (decoded, chain_id) = Signature::decode_with_eip155_chain_id(&mut &*encoded).unwrap();
assert_eq!(signature, decoded);
assert_eq!(None, chain_id);
let mut encoded = BytesMut::new();
signature.encode_eip155_inner(&mut encoded, 1);
let (decoded, chain_id) = Signature::decode_eip155_inner(&mut &*encoded).unwrap();
signature.encode_with_eip155_chain_id(&mut encoded, Some(1));
assert_eq!(encoded.len(), signature.payload_len_with_eip155_chain_id(Some(1)));
let (decoded, chain_id) = Signature::decode_with_eip155_chain_id(&mut &*encoded).unwrap();
assert_eq!(signature, decoded);
assert_eq!(Some(1), chain_id);
}
#[test]
fn test_payload_len() {
let signature = Signature { r: U256::default(), s: U256::default(), odd_y_parity: false };
assert_eq!(3, signature.payload_len());
}
#[test]
fn test_encode_and_decode() {
let signature = Signature { r: U256::default(), s: U256::default(), odd_y_parity: false };
let mut encoded = BytesMut::new();
signature.encode(&mut encoded);
assert_eq!(encoded.len(), signature.payload_len());
let decoded = Signature::decode(&mut &*encoded).unwrap();
assert_eq!(signature, decoded);
}
#[test]
fn test_recover_signer() {
let signature = Signature {