jam-std-common 0.1.26

Common datatypes and utilities for the JAM nodes and tooling
Documentation
use codec::{ConstEncodedLen, Decode, Encode, MaxEncodedLen};
use jam_types::{FixedVec, OpaqueValidatorMetadata};

use crate::{bandersnatch, ed25519, hash_raw_concat, PeerAddr, PeerDetails, PeerId};

#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, MaxEncodedLen)]
pub struct ValidatorMetadata {
	pub addr: PeerAddr,
	pub rest1: [u8; 14],
	pub rest2: [u32; 24],
}
impl ConstEncodedLen for ValidatorMetadata {}

impl Default for ValidatorMetadata {
	fn default() -> Self {
		Self {
			addr: PeerAddr { ip: Default::default(), port: 0 },
			rest1: Default::default(),
			rest2: Default::default(),
		}
	}
}

impl std::fmt::Debug for ValidatorMetadata {
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		write!(f, "{}", self.addr)
	}
}

impl TryFrom<OpaqueValidatorMetadata> for ValidatorMetadata {
	type Error = codec::Error;
	fn try_from(opaque: OpaqueValidatorMetadata) -> Result<Self, Self::Error> {
		Self::decode(&mut &opaque[..])
	}
}

impl From<ValidatorMetadata> for OpaqueValidatorMetadata {
	fn from(metadata: ValidatorMetadata) -> Self {
		let mut opaque = OpaqueValidatorMetadata::default();
		metadata.encode_to(&mut opaque.as_mut_slice());
		opaque
	}
}

/// BLS Placeholder
pub mod bls {
	use codec::{Decode, Encode, MaxEncodedLen};
	use jam_types::OpaqueBlsPublic;

	pub const BLS_PUBLIC_SERIALIZED_LEN: usize = 144;

	#[derive(Copy, Clone, Encode, Decode, Debug, Eq, PartialEq, MaxEncodedLen)]
	pub struct Public(pub [u8; BLS_PUBLIC_SERIALIZED_LEN]);

	impl Default for Public {
		fn default() -> Self {
			Public([0u8; BLS_PUBLIC_SERIALIZED_LEN])
		}
	}

	impl From<OpaqueBlsPublic> for Public {
		fn from(opaque: OpaqueBlsPublic) -> Self {
			Self(opaque.0)
		}
	}

	impl From<Public> for OpaqueBlsPublic {
		fn from(public: Public) -> Self {
			Self(public.0)
		}
	}
}

#[derive(Copy, Clone, Encode, Decode, Debug, Eq, PartialEq, MaxEncodedLen, Default)]
pub struct ValKeyset {
	pub bandersnatch: bandersnatch::Public,
	pub ed25519: ed25519::Public,
	pub bls: bls::Public,
	pub metadata: ValidatorMetadata,
}

impl From<&ValKeyset> for PeerDetails {
	fn from(keyset: &ValKeyset) -> PeerDetails {
		PeerDetails { id: PeerId(keyset.ed25519), addr: keyset.metadata.addr }
	}
}

pub type ValKeysets = FixedVec<ValKeyset, jam_types::ValCount>;
pub type EdKeys = FixedVec<ed25519::Public, jam_types::ValCount>;

pub struct SecretKeyset {
	pub bandersnatch: bandersnatch::Secret,
	pub ed25519: ed25519::Secret,
}

impl SecretKeyset {
	pub fn from_seed(seed: &[u8; 32]) -> Self {
		Self {
			bandersnatch: bandersnatch::Secret::from_seed(hash_raw_concat([
				b"jam_val_key_bandersnatch".as_slice(),
				seed.as_slice(),
			])),
			ed25519: ed25519::Secret::from_seed(hash_raw_concat([
				b"jam_val_key_ed25519".as_slice(),
				seed.as_slice(),
			])),
		}
	}

	pub fn trivial(id: u32) -> Self {
		[id; 8].using_encoded(|data| {
			Self::from_seed(data.try_into().expect("data is always 32 bytes"))
		})
	}

	pub fn public(&self, metadata: ValidatorMetadata) -> ValKeyset {
		ValKeyset {
			ed25519: self.ed25519.public(),
			bandersnatch: self.bandersnatch.public(),
			bls: bls::Public::default(),
			metadata,
		}
	}
}

// Items order of ValKeyset and OpaqueValKeyset must match
#[test]
fn validator_keyset_order_assumptions() {
	let keyset = SecretKeyset::trivial(0).public(Default::default());
	let buf = keyset.encode();
	let opaque = jam_types::OpaqueValKeyset::decode(&mut &buf[..]).unwrap();
	assert_eq!(keyset.bandersnatch.encode(), opaque.bandersnatch[..]);
	assert_eq!(keyset.ed25519.encode(), opaque.ed25519[..]);
	assert_eq!(keyset.bls.encode(), opaque.bls[..]);
	assert_eq!(keyset.metadata.encode(), opaque.metadata[..]);
	let buf = opaque.encode();
	let keyset2 = ValKeyset::decode(&mut &buf[..]).unwrap();
	assert_eq!(keyset, keyset2);
}