Update beacon node crates for new SSZ
This commit is contained in:
parent
d9bfbc2657
commit
eb62b5842d
@ -49,7 +49,7 @@ impl<TSubstream: AsyncRead + AsyncWrite> NetworkBehaviourEventProcess<GossipsubE
|
|||||||
GossipsubEvent::Message(gs_msg) => {
|
GossipsubEvent::Message(gs_msg) => {
|
||||||
trace!(self.log, "Received GossipEvent"; "msg" => format!("{:?}", gs_msg));
|
trace!(self.log, "Received GossipEvent"; "msg" => format!("{:?}", gs_msg));
|
||||||
|
|
||||||
let pubsub_message = match PubsubMessage::ssz_decode(&gs_msg.data, 0) {
|
let pubsub_message = match PubsubMessage::from_ssz_bytes(&gs_msg.data) {
|
||||||
//TODO: Punish peer on error
|
//TODO: Punish peer on error
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(
|
warn!(
|
||||||
@ -59,7 +59,7 @@ impl<TSubstream: AsyncRead + AsyncWrite> NetworkBehaviourEventProcess<GossipsubE
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Ok((msg, _index)) => msg,
|
Ok(msg) => msg,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.events.push(BehaviourEvent::GossipMessage {
|
self.events.push(BehaviourEvent::GossipMessage {
|
||||||
@ -198,33 +198,58 @@ pub enum PubsubMessage {
|
|||||||
|
|
||||||
//TODO: Correctly encode/decode enums. Prefixing with integer for now.
|
//TODO: Correctly encode/decode enums. Prefixing with integer for now.
|
||||||
impl Encodable for PubsubMessage {
|
impl Encodable for PubsubMessage {
|
||||||
fn ssz_append(&self, s: &mut SszStream) {
|
fn is_ssz_fixed_len() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||||
|
let offset = <u32 as Encodable>::ssz_fixed_len() + <Vec<u8> as Encodable>::ssz_fixed_len();
|
||||||
|
|
||||||
|
let mut encoder = ssz::SszEncoder::container(buf, offset);
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
PubsubMessage::Block(block_gossip) => {
|
PubsubMessage::Block(block_gossip) => {
|
||||||
0u32.ssz_append(s);
|
encoder.append(&0_u32);
|
||||||
block_gossip.ssz_append(s);
|
|
||||||
|
// Encode the gossip as a Vec<u8>;
|
||||||
|
encoder.append(&block_gossip.as_ssz_bytes());
|
||||||
}
|
}
|
||||||
PubsubMessage::Attestation(attestation_gossip) => {
|
PubsubMessage::Attestation(attestation_gossip) => {
|
||||||
1u32.ssz_append(s);
|
encoder.append(&1_u32);
|
||||||
attestation_gossip.ssz_append(s);
|
|
||||||
|
// Encode the gossip as a Vec<u8>;
|
||||||
|
encoder.append(&attestation_gossip.as_ssz_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
encoder.finalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for PubsubMessage {
|
impl Decodable for PubsubMessage {
|
||||||
fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
|
fn is_ssz_fixed_len() -> bool {
|
||||||
let (id, index) = u32::ssz_decode(bytes, index)?;
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, ssz::DecodeError> {
|
||||||
|
let mut builder = ssz::SszDecoderBuilder::new(&bytes);
|
||||||
|
|
||||||
|
builder.register_type::<u32>()?;
|
||||||
|
builder.register_type::<Vec<u8>>()?;
|
||||||
|
|
||||||
|
let mut decoder = builder.build()?;
|
||||||
|
|
||||||
|
let id: u32 = decoder.decode_next()?;
|
||||||
|
let body: Vec<u8> = decoder.decode_next()?;
|
||||||
|
|
||||||
match id {
|
match id {
|
||||||
0 => {
|
0 => Ok(PubsubMessage::Block(BeaconBlock::from_ssz_bytes(&body)?)),
|
||||||
let (block, index) = BeaconBlock::ssz_decode(bytes, index)?;
|
1 => Ok(PubsubMessage::Attestation(Attestation::from_ssz_bytes(
|
||||||
Ok((PubsubMessage::Block(block), index))
|
&body,
|
||||||
}
|
)?)),
|
||||||
1 => {
|
_ => Err(DecodeError::BytesInvalid(
|
||||||
let (attestation, index) = Attestation::ssz_decode(bytes, index)?;
|
"Invalid PubsubMessage id".to_string(),
|
||||||
Ok((PubsubMessage::Attestation(attestation), index))
|
)),
|
||||||
}
|
|
||||||
_ => Err(DecodeError::Invalid),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,9 +265,7 @@ mod test {
|
|||||||
|
|
||||||
let encoded = ssz_encode(&original);
|
let encoded = ssz_encode(&original);
|
||||||
|
|
||||||
println!("{:?}", encoded);
|
let decoded = PubsubMessage::from_ssz_bytes(&encoded).unwrap();
|
||||||
|
|
||||||
let (decoded, _i) = PubsubMessage::ssz_decode(&encoded, 0).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(original, decoded);
|
assert_eq!(original, decoded);
|
||||||
}
|
}
|
||||||
|
@ -115,42 +115,40 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE!
|
||||||
|
//
|
||||||
|
// This code has not been tested, it is a placeholder until we can update to the new libp2p
|
||||||
|
// spec.
|
||||||
fn decode(packet: Vec<u8>) -> Result<RPCEvent, DecodeError> {
|
fn decode(packet: Vec<u8>) -> Result<RPCEvent, DecodeError> {
|
||||||
// decode the header of the rpc
|
let mut builder = ssz::SszDecoderBuilder::new(&packet);
|
||||||
// request/response
|
|
||||||
let (request, index) = bool::ssz_decode(&packet, 0)?;
|
builder.register_type::<bool>()?;
|
||||||
let (id, index) = RequestId::ssz_decode(&packet, index)?;
|
builder.register_type::<RequestId>()?;
|
||||||
let (method_id, index) = u16::ssz_decode(&packet, index)?;
|
builder.register_type::<u16>()?;
|
||||||
|
builder.register_type::<Vec<u8>>()?;
|
||||||
|
|
||||||
|
let mut decoder = builder.build()?;
|
||||||
|
|
||||||
|
let request: bool = decoder.decode_next()?;
|
||||||
|
let id: RequestId = decoder.decode_next()?;
|
||||||
|
let method_id: u16 = decoder.decode_next()?;
|
||||||
|
let bytes: Vec<u8> = decoder.decode_next()?;
|
||||||
|
|
||||||
if request {
|
if request {
|
||||||
let body = match RPCMethod::from(method_id) {
|
let body = match RPCMethod::from(method_id) {
|
||||||
RPCMethod::Hello => {
|
RPCMethod::Hello => RPCRequest::Hello(HelloMessage::from_ssz_bytes(&bytes)?),
|
||||||
let (hello_body, _index) = HelloMessage::ssz_decode(&packet, index)?;
|
RPCMethod::Goodbye => RPCRequest::Goodbye(GoodbyeReason::from_ssz_bytes(&bytes)?),
|
||||||
RPCRequest::Hello(hello_body)
|
|
||||||
}
|
|
||||||
RPCMethod::Goodbye => {
|
|
||||||
let (goodbye_reason, _index) = GoodbyeReason::ssz_decode(&packet, index)?;
|
|
||||||
RPCRequest::Goodbye(goodbye_reason)
|
|
||||||
}
|
|
||||||
RPCMethod::BeaconBlockRoots => {
|
RPCMethod::BeaconBlockRoots => {
|
||||||
let (block_roots_request, _index) =
|
RPCRequest::BeaconBlockRoots(BeaconBlockRootsRequest::from_ssz_bytes(&bytes)?)
|
||||||
BeaconBlockRootsRequest::ssz_decode(&packet, index)?;
|
|
||||||
RPCRequest::BeaconBlockRoots(block_roots_request)
|
|
||||||
}
|
}
|
||||||
RPCMethod::BeaconBlockHeaders => {
|
RPCMethod::BeaconBlockHeaders => {
|
||||||
let (block_headers_request, _index) =
|
RPCRequest::BeaconBlockHeaders(BeaconBlockHeadersRequest::from_ssz_bytes(&bytes)?)
|
||||||
BeaconBlockHeadersRequest::ssz_decode(&packet, index)?;
|
|
||||||
RPCRequest::BeaconBlockHeaders(block_headers_request)
|
|
||||||
}
|
}
|
||||||
RPCMethod::BeaconBlockBodies => {
|
RPCMethod::BeaconBlockBodies => {
|
||||||
let (block_bodies_request, _index) =
|
RPCRequest::BeaconBlockBodies(BeaconBlockBodiesRequest::from_ssz_bytes(&bytes)?)
|
||||||
BeaconBlockBodiesRequest::ssz_decode(&packet, index)?;
|
|
||||||
RPCRequest::BeaconBlockBodies(block_bodies_request)
|
|
||||||
}
|
}
|
||||||
RPCMethod::BeaconChainState => {
|
RPCMethod::BeaconChainState => {
|
||||||
let (chain_state_request, _index) =
|
RPCRequest::BeaconChainState(BeaconChainStateRequest::from_ssz_bytes(&bytes)?)
|
||||||
BeaconChainStateRequest::ssz_decode(&packet, index)?;
|
|
||||||
RPCRequest::BeaconChainState(chain_state_request)
|
|
||||||
}
|
}
|
||||||
RPCMethod::Unknown => return Err(DecodeError::UnknownRPCMethod),
|
RPCMethod::Unknown => return Err(DecodeError::UnknownRPCMethod),
|
||||||
};
|
};
|
||||||
@ -164,29 +162,24 @@ fn decode(packet: Vec<u8>) -> Result<RPCEvent, DecodeError> {
|
|||||||
// we have received a response
|
// we have received a response
|
||||||
else {
|
else {
|
||||||
let result = match RPCMethod::from(method_id) {
|
let result = match RPCMethod::from(method_id) {
|
||||||
RPCMethod::Hello => {
|
RPCMethod::Hello => RPCResponse::Hello(HelloMessage::from_ssz_bytes(&bytes)?),
|
||||||
let (body, _index) = HelloMessage::ssz_decode(&packet, index)?;
|
|
||||||
RPCResponse::Hello(body)
|
|
||||||
}
|
|
||||||
RPCMethod::Goodbye => unreachable!("Should never receive a goodbye response"),
|
|
||||||
RPCMethod::BeaconBlockRoots => {
|
RPCMethod::BeaconBlockRoots => {
|
||||||
let (body, _index) = BeaconBlockRootsResponse::ssz_decode(&packet, index)?;
|
RPCResponse::BeaconBlockRoots(BeaconBlockRootsResponse::from_ssz_bytes(&bytes)?)
|
||||||
RPCResponse::BeaconBlockRoots(body)
|
|
||||||
}
|
}
|
||||||
RPCMethod::BeaconBlockHeaders => {
|
RPCMethod::BeaconBlockHeaders => {
|
||||||
let (body, _index) = BeaconBlockHeadersResponse::ssz_decode(&packet, index)?;
|
RPCResponse::BeaconBlockHeaders(BeaconBlockHeadersResponse::from_ssz_bytes(&bytes)?)
|
||||||
RPCResponse::BeaconBlockHeaders(body)
|
|
||||||
}
|
}
|
||||||
RPCMethod::BeaconBlockBodies => {
|
RPCMethod::BeaconBlockBodies => {
|
||||||
let (body, _index) = BeaconBlockBodiesResponse::ssz_decode(&packet, index)?;
|
RPCResponse::BeaconBlockBodies(BeaconBlockBodiesResponse::from_ssz_bytes(&packet)?)
|
||||||
RPCResponse::BeaconBlockBodies(body)
|
|
||||||
}
|
}
|
||||||
RPCMethod::BeaconChainState => {
|
RPCMethod::BeaconChainState => {
|
||||||
let (body, _index) = BeaconChainStateResponse::ssz_decode(&packet, index)?;
|
RPCResponse::BeaconChainState(BeaconChainStateResponse::from_ssz_bytes(&packet)?)
|
||||||
RPCResponse::BeaconChainState(body)
|
|
||||||
}
|
}
|
||||||
|
// We should never receive a goodbye response; it is invalid.
|
||||||
|
RPCMethod::Goodbye => return Err(DecodeError::UnknownRPCMethod),
|
||||||
RPCMethod::Unknown => return Err(DecodeError::UnknownRPCMethod),
|
RPCMethod::Unknown => return Err(DecodeError::UnknownRPCMethod),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(RPCEvent::Response {
|
Ok(RPCEvent::Response {
|
||||||
id,
|
id,
|
||||||
method_id,
|
method_id,
|
||||||
@ -211,34 +204,50 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for RPCEvent {
|
impl Encodable for RPCEvent {
|
||||||
fn ssz_append(&self, s: &mut SszStream) {
|
fn is_ssz_fixed_len() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE!
|
||||||
|
//
|
||||||
|
// This code has not been tested, it is a placeholder until we can update to the new libp2p
|
||||||
|
// spec.
|
||||||
|
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||||
|
let offset = <bool as Encodable>::ssz_fixed_len()
|
||||||
|
+ <u16 as Encodable>::ssz_fixed_len()
|
||||||
|
+ <Vec<u8> as Encodable>::ssz_fixed_len();
|
||||||
|
|
||||||
|
let mut encoder = ssz::SszEncoder::container(buf, offset);
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
RPCEvent::Request {
|
RPCEvent::Request {
|
||||||
id,
|
id,
|
||||||
method_id,
|
method_id,
|
||||||
body,
|
body,
|
||||||
} => {
|
} => {
|
||||||
s.append(&true);
|
encoder.append(&true);
|
||||||
s.append(id);
|
encoder.append(id);
|
||||||
s.append(method_id);
|
encoder.append(method_id);
|
||||||
|
|
||||||
|
// Encode the `body` as a `Vec<u8>`.
|
||||||
match body {
|
match body {
|
||||||
RPCRequest::Hello(body) => {
|
RPCRequest::Hello(body) => {
|
||||||
s.append(body);
|
encoder.append(&body.as_ssz_bytes());
|
||||||
}
|
}
|
||||||
RPCRequest::Goodbye(body) => {
|
RPCRequest::Goodbye(body) => {
|
||||||
s.append(body);
|
encoder.append(&body.as_ssz_bytes());
|
||||||
}
|
}
|
||||||
RPCRequest::BeaconBlockRoots(body) => {
|
RPCRequest::BeaconBlockRoots(body) => {
|
||||||
s.append(body);
|
encoder.append(&body.as_ssz_bytes());
|
||||||
}
|
}
|
||||||
RPCRequest::BeaconBlockHeaders(body) => {
|
RPCRequest::BeaconBlockHeaders(body) => {
|
||||||
s.append(body);
|
encoder.append(&body.as_ssz_bytes());
|
||||||
}
|
}
|
||||||
RPCRequest::BeaconBlockBodies(body) => {
|
RPCRequest::BeaconBlockBodies(body) => {
|
||||||
s.append(body);
|
encoder.append(&body.as_ssz_bytes());
|
||||||
}
|
}
|
||||||
RPCRequest::BeaconChainState(body) => {
|
RPCRequest::BeaconChainState(body) => {
|
||||||
s.append(body);
|
encoder.append(&body.as_ssz_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -247,28 +256,32 @@ impl Encodable for RPCEvent {
|
|||||||
method_id,
|
method_id,
|
||||||
result,
|
result,
|
||||||
} => {
|
} => {
|
||||||
s.append(&false);
|
encoder.append(&true);
|
||||||
s.append(id);
|
encoder.append(id);
|
||||||
s.append(method_id);
|
encoder.append(method_id);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
RPCResponse::Hello(response) => {
|
RPCResponse::Hello(response) => {
|
||||||
s.append(response);
|
encoder.append(&response.as_ssz_bytes());
|
||||||
}
|
}
|
||||||
RPCResponse::BeaconBlockRoots(response) => {
|
RPCResponse::BeaconBlockRoots(response) => {
|
||||||
s.append(response);
|
encoder.append(&response.as_ssz_bytes());
|
||||||
}
|
}
|
||||||
RPCResponse::BeaconBlockHeaders(response) => {
|
RPCResponse::BeaconBlockHeaders(response) => {
|
||||||
s.append(response);
|
encoder.append(&response.as_ssz_bytes());
|
||||||
}
|
}
|
||||||
RPCResponse::BeaconBlockBodies(response) => {
|
RPCResponse::BeaconBlockBodies(response) => {
|
||||||
s.append(response);
|
encoder.append(&response.as_ssz_bytes());
|
||||||
}
|
}
|
||||||
RPCResponse::BeaconChainState(response) => {
|
RPCResponse::BeaconChainState(response) => {
|
||||||
s.append(response);
|
encoder.append(&response.as_ssz_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finalize the encoder, writing to `buf`.
|
||||||
|
encoder.finalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,8 +110,8 @@ impl<B: EthSpec> AttestationService for AttestationServiceInstance<B> {
|
|||||||
let mut resp = PublishAttestationResponse::new();
|
let mut resp = PublishAttestationResponse::new();
|
||||||
let ssz_serialized_attestation = req.get_attestation().get_ssz();
|
let ssz_serialized_attestation = req.get_attestation().get_ssz();
|
||||||
|
|
||||||
let attestation = match Attestation::ssz_decode(ssz_serialized_attestation, 0) {
|
let attestation = match Attestation::from_ssz_bytes(ssz_serialized_attestation) {
|
||||||
Ok((v, _index)) => v,
|
Ok(v) => v,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let log_clone = self.log.clone();
|
let log_clone = self.log.clone();
|
||||||
let f = sink
|
let f = sink
|
||||||
|
@ -35,8 +35,8 @@ impl<B: EthSpec> BeaconBlockService for BeaconBlockServiceInstance<B> {
|
|||||||
// decode the request
|
// decode the request
|
||||||
// TODO: requested slot currently unused, see: https://github.com/sigp/lighthouse/issues/336
|
// TODO: requested slot currently unused, see: https://github.com/sigp/lighthouse/issues/336
|
||||||
let _requested_slot = Slot::from(req.get_slot());
|
let _requested_slot = Slot::from(req.get_slot());
|
||||||
let randao_reveal = match Signature::ssz_decode(req.get_randao_reveal(), 0) {
|
let randao_reveal = match Signature::from_ssz_bytes(req.get_randao_reveal()) {
|
||||||
Ok((reveal, _index)) => reveal,
|
Ok(reveal) => reveal,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// decode error, incorrect signature
|
// decode error, incorrect signature
|
||||||
let log_clone = self.log.clone();
|
let log_clone = self.log.clone();
|
||||||
@ -91,8 +91,8 @@ impl<B: EthSpec> BeaconBlockService for BeaconBlockServiceInstance<B> {
|
|||||||
|
|
||||||
let ssz_serialized_block = req.get_block().get_ssz();
|
let ssz_serialized_block = req.get_block().get_ssz();
|
||||||
|
|
||||||
match BeaconBlock::ssz_decode(ssz_serialized_block, 0) {
|
match BeaconBlock::from_ssz_bytes(ssz_serialized_block) {
|
||||||
Ok((block, _i)) => {
|
Ok(block) => {
|
||||||
match self.chain.process_block(block.clone()) {
|
match self.chain.process_block(block.clone()) {
|
||||||
Ok(outcome) => {
|
Ok(outcome) => {
|
||||||
if outcome.sucessfully_processed() {
|
if outcome.sucessfully_processed() {
|
||||||
|
@ -5,7 +5,7 @@ use grpcio::{RpcContext, RpcStatus, RpcStatusCode, UnarySink};
|
|||||||
use protos::services::{ActiveValidator, GetDutiesRequest, GetDutiesResponse, ValidatorDuty};
|
use protos::services::{ActiveValidator, GetDutiesRequest, GetDutiesResponse, ValidatorDuty};
|
||||||
use protos::services_grpc::ValidatorService;
|
use protos::services_grpc::ValidatorService;
|
||||||
use slog::{trace, warn};
|
use slog::{trace, warn};
|
||||||
use ssz::decode;
|
use ssz::Decodable;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::{Epoch, EthSpec, RelativeEpoch};
|
use types::{Epoch, EthSpec, RelativeEpoch};
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ impl<B: EthSpec> ValidatorService for ValidatorServiceInstance<B> {
|
|||||||
for validator_pk in validators.get_public_keys() {
|
for validator_pk in validators.get_public_keys() {
|
||||||
let mut active_validator = ActiveValidator::new();
|
let mut active_validator = ActiveValidator::new();
|
||||||
|
|
||||||
let public_key = match decode::<PublicKey>(validator_pk) {
|
let public_key = match PublicKey::from_ssz_bytes(validator_pk) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let log_clone = self.log.clone();
|
let log_clone = self.log.clone();
|
||||||
|
@ -80,7 +80,7 @@ impl<'de> Deserialize<'de> for FakeAggregateSignature {
|
|||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let bytes = deserializer.deserialize_str(PrefixedHexVisitor)?;
|
let bytes = deserializer.deserialize_str(PrefixedHexVisitor)?;
|
||||||
let (obj, _) = <_>::ssz_decode(&bytes[..], 0)
|
let obj = <_>::from_ssz_bytes(&bytes[..])
|
||||||
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
|
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
|
||||||
Ok(obj)
|
Ok(obj)
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ mod tests {
|
|||||||
original.add(&Signature::new(&[42, 42], 0, &keypair.sk));
|
original.add(&Signature::new(&[42, 42], 0, &keypair.sk));
|
||||||
|
|
||||||
let bytes = ssz_encode(&original);
|
let bytes = ssz_encode(&original);
|
||||||
let (decoded, _) = FakeAggregateSignature::ssz_decode(&bytes, 0).unwrap();
|
let decoded = FakeAggregateSignature::from_ssz_bytes(&bytes).unwrap();
|
||||||
|
|
||||||
assert_eq!(original, decoded);
|
assert_eq!(original, decoded);
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ impl<'de> Deserialize<'de> for FakeSignature {
|
|||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let bytes = deserializer.deserialize_str(HexVisitor)?;
|
let bytes = deserializer.deserialize_str(HexVisitor)?;
|
||||||
let (pubkey, _) = <_>::ssz_decode(&bytes[..], 0)
|
let pubkey = <_>::from_ssz_bytes(&bytes[..])
|
||||||
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
|
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
|
||||||
Ok(pubkey)
|
Ok(pubkey)
|
||||||
}
|
}
|
||||||
@ -94,7 +94,7 @@ mod tests {
|
|||||||
let original = FakeSignature::new(&[42, 42], 0, &keypair.sk);
|
let original = FakeSignature::new(&[42, 42], 0, &keypair.sk);
|
||||||
|
|
||||||
let bytes = ssz_encode(&original);
|
let bytes = ssz_encode(&original);
|
||||||
let (decoded, _) = FakeSignature::ssz_decode(&bytes, 0).unwrap();
|
let decoded = FakeSignature::from_ssz_bytes(&bytes).unwrap();
|
||||||
|
|
||||||
assert_eq!(original, decoded);
|
assert_eq!(original, decoded);
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,10 @@ pub trait Encodable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Allow for encoding an ordered series of distinct or indistinct objects as SSZ bytes.
|
||||||
|
///
|
||||||
|
/// **You must call `finalize(..)` after the final `append(..)` call** to ensure the bytes are
|
||||||
|
/// written to `buf`.
|
||||||
pub struct SszEncoder<'a> {
|
pub struct SszEncoder<'a> {
|
||||||
offset: usize,
|
offset: usize,
|
||||||
buf: &'a mut Vec<u8>,
|
buf: &'a mut Vec<u8>,
|
||||||
|
Loading…
Reference in New Issue
Block a user