feat: Add constants for known miniprotocols

* Add constants for known miniprotocols

Now consumers of the crate don't have to memorize what channel number means what

* Add myself to the crate authors
This commit is contained in:
Pi Lanningham 2023-02-05 06:13:55 -05:00 committed by GitHub
parent d869169e68
commit f9263a0eba
13 changed files with 122 additions and 79 deletions

View file

@ -2,7 +2,7 @@ use pallas::network::{
miniprotocols::{ miniprotocols::{
blockfetch, blockfetch,
handshake::{self, n2n::VersionTable}, handshake::{self, n2n::VersionTable},
Point, TESTNET_MAGIC, Point, PROTOCOL_N2N_BLOCK_FETCH, PROTOCOL_N2N_HANDSHAKE, TESTNET_MAGIC,
}, },
multiplexer::{bearers::Bearer, StdPlexer}, multiplexer::{bearers::Bearer, StdPlexer},
}; };
@ -13,14 +13,14 @@ fn main() {
let bearer = Bearer::connect_tcp("relays-new.cardano-testnet.iohkdev.io:3001").unwrap(); let bearer = Bearer::connect_tcp("relays-new.cardano-testnet.iohkdev.io:3001").unwrap();
let mut plexer = StdPlexer::new(bearer); let mut plexer = StdPlexer::new(bearer);
let channel0 = plexer.use_channel(0); let handshake = plexer.use_channel(PROTOCOL_N2N_HANDSHAKE);
let channel3 = plexer.use_channel(3); let blockfetch = plexer.use_channel(PROTOCOL_N2N_BLOCK_FETCH);
plexer.muxer.spawn(); plexer.muxer.spawn();
plexer.demuxer.spawn(); plexer.demuxer.spawn();
let versions = VersionTable::v4_and_above(TESTNET_MAGIC); let versions = VersionTable::v4_and_above(TESTNET_MAGIC);
let mut hs_client = handshake::N2NClient::new(channel0); let mut hs_client = handshake::N2NClient::new(handshake);
let handshake = hs_client.handshake(versions).unwrap(); let handshake = hs_client.handshake(versions).unwrap();
assert!(matches!(handshake, handshake::Confirmation::Accepted(..))); assert!(matches!(handshake, handshake::Confirmation::Accepted(..)));
@ -30,7 +30,7 @@ fn main() {
hex::decode("3f3d81c7b88f0fa28867541c5fea8794125cccf6d6c9ee0037a1dbb064130dfd").unwrap(), hex::decode("3f3d81c7b88f0fa28867541c5fea8794125cccf6d6c9ee0037a1dbb064130dfd").unwrap(),
); );
let mut bf_client = blockfetch::Client::new(channel3); let mut bf_client = blockfetch::Client::new(blockfetch);
let block = bf_client.fetch_single(point).unwrap(); let block = bf_client.fetch_single(point).unwrap();

View file

@ -1,5 +1,8 @@
use pallas::network::{ use pallas::network::{
miniprotocols::{chainsync, handshake, localstate, Point, MAINNET_MAGIC}, miniprotocols::{
chainsync, handshake, localstate, Point, MAINNET_MAGIC, PROTOCOL_N2C_CHAIN_SYNC,
PROTOCOL_N2C_HANDSHAKE, PROTOCOL_N2C_STATE_QUERY,
},
multiplexer::{self, bearers::Bearer}, multiplexer::{self, bearers::Bearer},
}; };
@ -75,19 +78,19 @@ fn main() {
// setup the multiplexer by specifying the bearer and the IDs of the // setup the multiplexer by specifying the bearer and the IDs of the
// miniprotocols to use // miniprotocols to use
let mut plexer = multiplexer::StdPlexer::new(bearer); let mut plexer = multiplexer::StdPlexer::new(bearer);
let channel0 = plexer.use_channel(0); let handshake = plexer.use_channel(PROTOCOL_N2C_HANDSHAKE);
let channel7 = plexer.use_channel(7); let statequery = plexer.use_channel(PROTOCOL_N2C_STATE_QUERY);
let channel5 = plexer.use_channel(5); let chainsync = plexer.use_channel(PROTOCOL_N2C_CHAIN_SYNC);
plexer.muxer.spawn(); plexer.muxer.spawn();
plexer.demuxer.spawn(); plexer.demuxer.spawn();
// execute the required handshake against the relay // execute the required handshake against the relay
do_handshake(channel0); do_handshake(handshake);
// execute an arbitrary "Local State" query against the node // execute an arbitrary "Local State" query against the node
do_localstate_query(channel7); do_localstate_query(statequery);
// execute the chainsync flow from an arbitrary point in the chain // execute the chainsync flow from an arbitrary point in the chain
do_chainsync(channel5); do_chainsync(chainsync);
} }

View file

@ -1,5 +1,8 @@
use pallas::network::{ use pallas::network::{
miniprotocols::{blockfetch, chainsync, handshake, Point, MAINNET_MAGIC}, miniprotocols::{
blockfetch, chainsync, handshake, Point, MAINNET_MAGIC, PROTOCOL_N2N_BLOCK_FETCH,
PROTOCOL_N2N_CHAIN_SYNC, PROTOCOL_N2N_HANDSHAKE,
},
multiplexer::{bearers::Bearer, StdChannel, StdPlexer}, multiplexer::{bearers::Bearer, StdChannel, StdPlexer},
}; };
@ -83,19 +86,19 @@ fn main() {
// setup the multiplexer by specifying the bearer and the IDs of the // setup the multiplexer by specifying the bearer and the IDs of the
// miniprotocols to use // miniprotocols to use
let mut plexer = StdPlexer::new(bearer); let mut plexer = StdPlexer::new(bearer);
let channel0 = plexer.use_channel(0); let handshake = plexer.use_channel(PROTOCOL_N2N_HANDSHAKE);
let channel3 = plexer.use_channel(3); let blockfetch = plexer.use_channel(PROTOCOL_N2N_BLOCK_FETCH);
let channel2 = plexer.use_channel(2); let chainsync = plexer.use_channel(PROTOCOL_N2N_CHAIN_SYNC);
plexer.muxer.spawn(); plexer.muxer.spawn();
plexer.demuxer.spawn(); plexer.demuxer.spawn();
// execute the required handshake against the relay // execute the required handshake against the relay
do_handshake(channel0); do_handshake(handshake);
// fetch an arbitrary batch of block // fetch an arbitrary batch of block
do_blockfetch(channel3); do_blockfetch(blockfetch);
// execute the chainsync flow from an arbitrary point in the chain // execute the chainsync flow from an arbitrary point in the chain
do_chainsync(channel2); do_chainsync(chainsync);
} }

View file

@ -7,7 +7,6 @@
//! //!
//! However, only the [`SecretKeyExtended`] can be used for HD derivation //! However, only the [`SecretKeyExtended`] can be used for HD derivation
//! (using [ed25519_bip32] or otherwise). //! (using [ed25519_bip32] or otherwise).
//!
use crate::memsec::Scrubbed as _; use crate::memsec::Scrubbed as _;
use cryptoxide::ed25519::{ use cryptoxide::ed25519::{
@ -18,13 +17,13 @@ use std::{any::type_name, convert::TryFrom, fmt, str::FromStr};
use thiserror::Error; use thiserror::Error;
/// Ed25519 Secret Key /// Ed25519 Secret Key
///
#[derive(Clone)] #[derive(Clone)]
pub struct SecretKey([u8; Self::SIZE]); pub struct SecretKey([u8; Self::SIZE]);
/// Ed25519 Extended Secret Key /// Ed25519 Extended Secret Key
/// ///
/// unlike [`SecretKey`], an extended key can be derived see [`pallas_crypto::derivation`] /// unlike [`SecretKey`], an extended key can be derived see
/// [`pallas_crypto::derivation`]
#[derive(Clone)] #[derive(Clone)]
pub struct SecretKeyExtended([u8; Self::SIZE]); pub struct SecretKeyExtended([u8; Self::SIZE]);
@ -77,7 +76,6 @@ impl_size_zero!(Signature, SIGNATURE_LENGTH);
impl SecretKey { impl SecretKey {
/// generate a new [`SecretKey`] with the given random number generator /// generate a new [`SecretKey`] with the given random number generator
///
pub fn new<Rng>(mut rng: Rng) -> Self pub fn new<Rng>(mut rng: Rng) -> Self
where where
Rng: RngCore + CryptoRng, Rng: RngCore + CryptoRng,
@ -106,8 +104,8 @@ impl SecretKey {
/// create a [`Signature`] for the given message with this [`SecretKey`]. /// create a [`Signature`] for the given message with this [`SecretKey`].
/// ///
/// The [`Signature`] can then be verified against the associated [`PublicKey`] /// The [`Signature`] can then be verified against the associated
/// and the original message. /// [`PublicKey`] and the original message.
pub fn sign<T>(&self, msg: T) -> Signature pub fn sign<T>(&self, msg: T) -> Signature
where where
T: AsRef<[u8]>, T: AsRef<[u8]>,
@ -125,8 +123,8 @@ impl SecretKey {
} }
impl SecretKeyExtended { impl SecretKeyExtended {
/// generate a new [`SecretKeyExtended`] with the given random number generator /// generate a new [`SecretKeyExtended`] with the given random number
/// /// generator
pub fn new<Rng>(mut rng: Rng) -> Self pub fn new<Rng>(mut rng: Rng) -> Self
where where
Rng: RngCore + CryptoRng, Rng: RngCore + CryptoRng,
@ -180,7 +178,6 @@ impl SecretKeyExtended {
impl PublicKey { impl PublicKey {
/// verify the cryptographic [`Signature`] against the `message` and the /// verify the cryptographic [`Signature`] against the `message` and the
/// [`PublicKey`] `self`. /// [`PublicKey`] `self`.
///
#[inline] #[inline]
pub fn verify<T>(&self, message: T, signature: &Signature) -> bool pub fn verify<T>(&self, message: T, signature: &Signature) -> bool
where where
@ -438,11 +435,12 @@ mod tests {
signature: Signature, signature: Signature,
message: Vec<u8>, message: Vec<u8>,
) -> bool { ) -> bool {
// NOTE: this test may fail but it is impossible to see this happening in normal condition. // NOTE: this test may fail but it is impossible to see this happening in normal
// we are generating 32 random bytes of public key and 64 random bytes // condition. we are generating 32 random bytes of public key and
// of signature with an randomly generated message of a random number // 64 random bytes of signature with an randomly generated message
// of bytes in. If the message were empty, the probability to have // of a random number of bytes in. If the message were empty, the
// a signature that matches the verify key would still be 1 out of 2^96. // probability to have a signature that matches the verify key
// would still be 1 out of 2^96.
// //
// if this test fails and it is not a bug, go buy a lottery ticket. // if this test fails and it is not a bug, go buy a lottery ticket.
!public_key.verify(message, &signature) !public_key.verify(message, &signature)

View file

@ -8,7 +8,10 @@ homepage = "https://github.com/txpipe/pallas"
documentation = "https://docs.rs/pallas-machines" documentation = "https://docs.rs/pallas-machines"
license = "Apache-2.0" license = "Apache-2.0"
readme = "README.md" readme = "README.md"
authors = ["Santiago Carmuega <santiago@carmuega.me>"] authors = [
"Santiago Carmuega <santiago@carmuega.me>",
"Pi Lanningham <pi.lanningham@gmail.com>"
]
[dependencies] [dependencies]
pallas-codec = { version = "0.18.0", path = "../pallas-codec/" } pallas-codec = { version = "0.18.0", path = "../pallas-codec/" }

View file

@ -71,7 +71,7 @@ bearer.set_keepalive_ms(Some(30_000u32)).unwrap();
let mut muxer = Multiplexer::setup(bearer, &[0]).unwrap(); let mut muxer = Multiplexer::setup(bearer, &[0]).unwrap();
// get a handle for the handhsake mini-protocol handle // get a handle for the handhsake mini-protocol handle
let mut channel = muxer.use_channel(0); let mut channel = muxer.use_channel(pallas_miniprotocols::PROTOCOL_N2N_HANDSHAKE);
// create a handshake client agent with an initial state // create a handshake client agent with an initial state
let agent = handshake::Client::initial(VersionTable::v4_and_above(MAINNET_MAGIC)); let agent = handshake::Client::initial(VersionTable::v4_and_above(MAINNET_MAGIC));

View file

@ -14,6 +14,33 @@ pub const PREVIEW_MAGIC: u64 = 2;
/// Well-known magic for pre-production /// Well-known magic for pre-production
pub const PRE_PRODUCTION_MAGIC: u64 = 1; pub const PRE_PRODUCTION_MAGIC: u64 = 1;
/// Protocol channel number for node-to-node handshakes
pub const PROTOCOL_N2N_HANDSHAKE: u16 = 0;
/// Protocol channel number for node-to-node chain-sync
pub const PROTOCOL_N2N_CHAIN_SYNC: u16 = 2;
/// Protocol channel number for node-to-node block-fetch
pub const PROTOCOL_N2N_BLOCK_FETCH: u16 = 3;
/// Protocol channel number for node-to-node tx-submission
pub const PROTOCOL_N2N_TX_SUBMISSION: u16 = 4;
/// Protocol channel number for node-to-node Keep-alive
pub const PROTOCOL_N2N_KEEP_ALIVE: u16 = 8;
/// Protocol channel number for node-to-client handshakes
pub const PROTOCOL_N2C_HANDSHAKE: u16 = 0;
/// Protocol channel number for node-to-client chain-sync
pub const PROTOCOL_N2C_CHAIN_SYNC: u16 = 5;
/// Protocol channel number for node-to-client tx-submission
pub const PROTOCOL_N2C_TX_SUBMISSION: u16 = 6;
// Protocol channel number for node-to-client state queries
pub const PROTOCOL_N2C_STATE_QUERY: u16 = 7;
/// A point within a chain /// A point within a chain
#[derive(Clone, Eq, PartialEq, Hash)] #[derive(Clone, Eq, PartialEq, Hash)]
pub enum Point { pub enum Point {

View file

@ -31,7 +31,8 @@ where
self.0 == State::Done self.0 == State::Done
} }
// NOTE(pi): as of this writing, the network spec has a typo; this is the correct behavior // NOTE(pi): as of this writing, the network spec has a typo; this is the
// correct behavior
fn has_agency(&self) -> bool { fn has_agency(&self) -> bool {
!matches!(self.state(), State::Idle) !matches!(self.state(), State::Idle)
} }

View file

@ -31,7 +31,8 @@ where
self.0 == State::Done self.0 == State::Done
} }
// NOTE(pi): as of this writing, the network spec has a typo; this is the correct behavior // NOTE(pi): as of this writing, the network spec has a typo; this is the
// correct behavior
fn has_agency(&self) -> bool { fn has_agency(&self) -> bool {
matches!(self.state(), State::Idle) matches!(self.state(), State::Idle)
} }

View file

@ -3,29 +3,30 @@ use pallas_miniprotocols::{
chainsync::{self, NextResponse}, chainsync::{self, NextResponse},
handshake::{self, Confirmation}, handshake::{self, Confirmation},
txsubmission::{self, Reply}, txsubmission::{self, Reply},
Point, Point, PROTOCOL_N2N_BLOCK_FETCH, PROTOCOL_N2N_CHAIN_SYNC, PROTOCOL_N2N_HANDSHAKE,
PROTOCOL_N2N_TX_SUBMISSION,
}; };
use pallas_multiplexer::{bearers::Bearer, StdChannel, StdPlexer}; use pallas_multiplexer::{bearers::Bearer, StdChannel, StdPlexer};
struct N2NChannels { struct N2NChannels {
channel2: StdChannel, chainsync: StdChannel,
channel3: StdChannel, blockfetch: StdChannel,
channel4: StdChannel, txsubmission: StdChannel,
} }
fn setup_n2n_client_connection() -> N2NChannels { fn setup_n2n_client_connection() -> N2NChannels {
let bearer = Bearer::connect_tcp("preview-node.world.dev.cardano.org:30002").unwrap(); let bearer = Bearer::connect_tcp("preview-node.world.dev.cardano.org:30002").unwrap();
let mut plexer = StdPlexer::new(bearer); let mut plexer = StdPlexer::new(bearer);
let channel0 = plexer.use_channel(0); let handshake = plexer.use_channel(PROTOCOL_N2N_HANDSHAKE);
let channel2 = plexer.use_channel(2); let chainsync = plexer.use_channel(PROTOCOL_N2N_CHAIN_SYNC);
let channel3 = plexer.use_channel(3); let blockfetch = plexer.use_channel(PROTOCOL_N2N_BLOCK_FETCH);
let channel4 = plexer.use_channel(4); let txsubmission = plexer.use_channel(PROTOCOL_N2N_TX_SUBMISSION);
plexer.muxer.spawn(); plexer.muxer.spawn();
plexer.demuxer.spawn(); plexer.demuxer.spawn();
let mut client = handshake::N2NClient::new(channel0); let mut client = handshake::N2NClient::new(handshake);
let confirmation = client let confirmation = client
.handshake(handshake::n2n::VersionTable::v7_and_above(2)) .handshake(handshake::n2n::VersionTable::v7_and_above(2))
@ -38,23 +39,23 @@ fn setup_n2n_client_connection() -> N2NChannels {
} }
N2NChannels { N2NChannels {
channel2, chainsync,
channel3, blockfetch,
channel4, txsubmission,
} }
} }
#[test] #[test]
#[ignore] #[ignore]
pub fn chainsync_history_happy_path() { pub fn chainsync_history_happy_path() {
let N2NChannels { channel2, .. } = setup_n2n_client_connection(); let N2NChannels { chainsync, .. } = setup_n2n_client_connection();
let known_point = Point::Specific( let known_point = Point::Specific(
1654413, 1654413,
hex::decode("7de1f036df5a133ce68a82877d14354d0ba6de7625ab918e75f3e2ecb29771c2").unwrap(), hex::decode("7de1f036df5a133ce68a82877d14354d0ba6de7625ab918e75f3e2ecb29771c2").unwrap(),
); );
let mut client = chainsync::N2NClient::new(channel2); let mut client = chainsync::N2NClient::new(chainsync);
let (point, _) = client.find_intersect(vec![known_point.clone()]).unwrap(); let (point, _) = client.find_intersect(vec![known_point.clone()]).unwrap();
@ -93,9 +94,9 @@ pub fn chainsync_history_happy_path() {
#[test] #[test]
#[ignore] #[ignore]
pub fn chainsync_tip_happy_path() { pub fn chainsync_tip_happy_path() {
let N2NChannels { channel2, .. } = setup_n2n_client_connection(); let N2NChannels { chainsync, .. } = setup_n2n_client_connection();
let mut client = chainsync::N2NClient::new(channel2); let mut client = chainsync::N2NClient::new(chainsync);
client.intersect_tip().unwrap(); client.intersect_tip().unwrap();
@ -132,14 +133,14 @@ pub fn chainsync_tip_happy_path() {
#[test] #[test]
#[ignore] #[ignore]
pub fn blockfetch_happy_path() { pub fn blockfetch_happy_path() {
let N2NChannels { channel3, .. } = setup_n2n_client_connection(); let N2NChannels { blockfetch, .. } = setup_n2n_client_connection();
let known_point = Point::Specific( let known_point = Point::Specific(
1654413, 1654413,
hex::decode("7de1f036df5a133ce68a82877d14354d0ba6de7625ab918e75f3e2ecb29771c2").unwrap(), hex::decode("7de1f036df5a133ce68a82877d14354d0ba6de7625ab918e75f3e2ecb29771c2").unwrap(),
); );
let mut client = blockfetch::Client::new(channel3); let mut client = blockfetch::Client::new(blockfetch);
let range_ok = client.request_range((known_point.clone(), known_point.clone())); let range_ok = client.request_range((known_point.clone(), known_point.clone()));
@ -170,13 +171,14 @@ pub fn blockfetch_happy_path() {
#[test] #[test]
#[ignore] #[ignore]
pub fn txsubmission_server_happy_path() { pub fn txsubmission_server_happy_path() {
// TODO(pi): Note that the below doesn't work; we need a node to connect *to us* during the integration test // TODO(pi): Note that the below doesn't work; we need a node to connect *to us*
// which seems awkward; // during the integration test which seems awkward;
// Alternatively, we can just set up both a client and server connecting to themselves for testing! // Alternatively, we can just set up both a client and server connecting to
// themselves for testing!
let N2NChannels { channel4, .. } = setup_n2n_client_connection(); let N2NChannels { txsubmission, .. } = setup_n2n_client_connection();
let mut server = txsubmission::Server::new(channel4); let mut server = txsubmission::Server::new(txsubmission);
assert!(matches!(server.wait_for_init(), Ok(_))); assert!(matches!(server.wait_for_init(), Ok(_)));
@ -209,7 +211,8 @@ pub fn txsubmission_server_happy_path() {
assert!(matches!(reply, Ok(Reply::Txs(_)))); assert!(matches!(reply, Ok(Reply::Txs(_))));
let Ok(Reply::Txs(second_txs)) = reply else { unreachable!() }; let Ok(Reply::Txs(second_txs)) = reply else { unreachable!() };
// Make sure we receive the second and third tx again, indicating we sent the `acknowledge 1` bit correctly // Make sure we receive the second and third tx again, indicating we sent the
// `acknowledge 1` bit correctly
assert_eq!(second_txs[0], first_txs[1]); assert_eq!(second_txs[0], first_txs[1]);
assert_eq!(second_txs[1], first_txs[2]); assert_eq!(second_txs[1], first_txs[2]);

View file

@ -34,13 +34,13 @@ let bearer = UnixStream::connect("/tmp/pallas").unwrap();
let muxer = Multiplexer::setup(tcp, &[0, 2]) let muxer = Multiplexer::setup(tcp, &[0, 2])
// Ask the multiplexer to provide us with the channel for the miniprotocol #0. // Ask the multiplexer to provide us with the channel for the miniprotocol #0.
let mut channel_0 = muxer.use_channel(0); let mut handshake = muxer.use_channel(PROTOCOL_N2N_HANDSHAKE);
// Spawn a thread and pass the ownership of the channel. // Spawn a thread and pass the ownership of the channel.
thread::spawn(move || { thread::spawn(move || {
// Deconstruct the channel to get a handle for sending data into the muxer // Deconstruct the channel to get a handle for sending data into the muxer
// ingress and a handle to receive data from the demuxer egress. // ingress and a handle to receive data from the demuxer egress.
let Channel(mux_tx, demux_rx) = channel_0; let Channel(mux_tx, demux_rx) = handshake;
// Do something with the channel. In this case, we just keep sending // Do something with the channel. In this case, we just keep sending
// dumb data every 50 millis. // dumb data every 50 millis.
@ -51,14 +51,14 @@ thread::spawn(move || {
} }
}); });
// Ask the multiplexer to provide us with the channel for the miniprotocol #2. // Ask the multiplexer to provide us with the channel for the chainsync miniprotocol.
let mut channel_2 = muxer.use_channel(2); let mut chainsync = muxer.use_channel(PROTOCOL_N2N_CHAINSYNC);
// Spawn a different thread and pass the ownership of the 2nd channel. // Spawn a different thread and pass the ownership of the 2nd channel.
thread::spawn(move || { thread::spawn(move || {
// Deconstruct the channel to get a handle for sending data into the muxer // Deconstruct the channel to get a handle for sending data into the muxer
// ingress and a handle to receive data from the demuxer egress. // ingress and a handle to receive data from the demuxer egress.
let Channel(mux_tx, demux_rx) = channel_2; let Channel(mux_tx, demux_rx) = chainsync;
// Do something with the channel. In this case, we just print in stdout // Do something with the channel. In this case, we just print in stdout
// whatever get received for this mini-protocol. // whatever get received for this mini-protocol.

View file

@ -844,7 +844,8 @@ impl AsRef<[u8]> for PlutusScript {
} }
} }
/// Defined to encode PlutusData bytestring as it is done in the canonical plutus implementation /// Defined to encode PlutusData bytestring as it is done in the canonical
/// plutus implementation
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[serde(into = "String")] #[serde(into = "String")]
#[serde(try_from = "String")] #[serde(try_from = "String")]
@ -899,7 +900,8 @@ impl<C> Encode<C> for BoundedBytes {
e: &mut minicbor::Encoder<W>, e: &mut minicbor::Encoder<W>,
_: &mut C, _: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> { ) -> Result<(), minicbor::encode::Error<W::Error>> {
// we match the haskell implementation by encoding bytestrings longer than 64 bytes as indefinite lists of bytes // we match the haskell implementation by encoding bytestrings longer than 64
// bytes as indefinite lists of bytes
const CHUNK_SIZE: usize = 64; const CHUNK_SIZE: usize = 64;
let bs: &Vec<u8> = self.deref(); let bs: &Vec<u8> = self.deref();
if bs.len() <= 64 { if bs.len() <= 64 {
@ -1086,8 +1088,8 @@ impl<C> minicbor::encode::Encode<C> for PlutusData {
e.encode_with(a, ctx)?; e.encode_with(a, ctx)?;
} }
Self::Map(a) => { Self::Map(a) => {
// we use definite array to match the approach used by haskell's plutus implementation // we use definite array to match the approach used by haskell's plutus
// https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L152 // implementation https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L152
e.map(a.len().try_into().unwrap())?; e.map(a.len().try_into().unwrap())?;
for (k, v) in a.iter() { for (k, v) in a.iter() {
k.encode(e, ctx)?; k.encode(e, ctx)?;
@ -1101,8 +1103,8 @@ impl<C> minicbor::encode::Encode<C> for PlutusData {
e.encode_with(a, ctx)?; e.encode_with(a, ctx)?;
} }
Self::Array(a) => { Self::Array(a) => {
// we use definite array for empty array or indef array otherwise to match haskell implementation // we use definite array for empty array or indef array otherwise to match
// https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L153 // haskell implementation https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L153
// default encoder for a list: // default encoder for a list:
// https://github.com/well-typed/cborg/blob/4bdc818a1f0b35f38bc118a87944630043b58384/serialise/src/Codec/Serialise/Class.hs#L181 // https://github.com/well-typed/cborg/blob/4bdc818a1f0b35f38bc118a87944630043b58384/serialise/src/Codec/Serialise/Class.hs#L181
encode_list(a, e, ctx)?; encode_list(a, e, ctx)?;
@ -1172,15 +1174,16 @@ where
e.array(2)?; e.array(2)?;
e.encode_with(self.any_constructor.unwrap_or_default(), ctx)?; e.encode_with(self.any_constructor.unwrap_or_default(), ctx)?;
// we use definite array for empty array or indef array otherwise to match haskell implementation // we use definite array for empty array or indef array otherwise to match
// https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L144 // haskell implementation https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L144
// default encoder for a list: // default encoder for a list:
// https://github.com/well-typed/cborg/blob/4bdc818a1f0b35f38bc118a87944630043b58384/serialise/src/Codec/Serialise/Class.hs#L181 // https://github.com/well-typed/cborg/blob/4bdc818a1f0b35f38bc118a87944630043b58384/serialise/src/Codec/Serialise/Class.hs#L181
encode_list(&self.fields, e, ctx)?; encode_list(&self.fields, e, ctx)?;
Ok(()) Ok(())
} }
_ => { _ => {
// we use definite array for empty array or indef array otherwise to match haskell implementation. See above reference. // we use definite array for empty array or indef array otherwise to match
// haskell implementation. See above reference.
encode_list(&self.fields, e, ctx)?; encode_list(&self.fields, e, ctx)?;
Ok(()) Ok(())
} }

View file

@ -232,14 +232,15 @@ impl<'b> MultiEraTx<'b> {
} }
} }
/// Returns a list of tuples of the outputs produced by the Tx with their indexes /// Returns a list of tuples of the outputs produced by the Tx with their
/// indexes
/// ///
/// Helper method to abstract the logic of which outputs are produced /// Helper method to abstract the logic of which outputs are produced
/// depending on the validity of the Tx. If the Tx is valid, this method /// depending on the validity of the Tx. If the Tx is valid, this method
/// will return the list of outputs. If the Tx is invalid it will return the /// will return the list of outputs. If the Tx is invalid it will return the
/// collateral return if one is present or an empty list if not. Note that the /// collateral return if one is present or an empty list if not. Note that
/// collateral return output index is defined as the next available index after /// the collateral return output index is defined as the next available
/// the txouts (Babbage spec, ch 4). /// index after the txouts (Babbage spec, ch 4).
pub fn produces(&self) -> Vec<(usize, MultiEraOutput)> { pub fn produces(&self) -> Vec<(usize, MultiEraOutput)> {
match self.is_valid() { match self.is_valid() {
true => self.outputs().into_iter().enumerate().collect(), true => self.outputs().into_iter().enumerate().collect(),