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:
parent
f795948d2f
commit
4915d14cd5
13 changed files with 122 additions and 79 deletions
|
|
@ -2,7 +2,7 @@ use pallas::network::{
|
|||
miniprotocols::{
|
||||
blockfetch,
|
||||
handshake::{self, n2n::VersionTable},
|
||||
Point, TESTNET_MAGIC,
|
||||
Point, PROTOCOL_N2N_BLOCK_FETCH, PROTOCOL_N2N_HANDSHAKE, TESTNET_MAGIC,
|
||||
},
|
||||
multiplexer::{bearers::Bearer, StdPlexer},
|
||||
};
|
||||
|
|
@ -13,14 +13,14 @@ fn main() {
|
|||
let bearer = Bearer::connect_tcp("relays-new.cardano-testnet.iohkdev.io:3001").unwrap();
|
||||
|
||||
let mut plexer = StdPlexer::new(bearer);
|
||||
let channel0 = plexer.use_channel(0);
|
||||
let channel3 = plexer.use_channel(3);
|
||||
let handshake = plexer.use_channel(PROTOCOL_N2N_HANDSHAKE);
|
||||
let blockfetch = plexer.use_channel(PROTOCOL_N2N_BLOCK_FETCH);
|
||||
|
||||
plexer.muxer.spawn();
|
||||
plexer.demuxer.spawn();
|
||||
|
||||
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();
|
||||
|
||||
assert!(matches!(handshake, handshake::Confirmation::Accepted(..)));
|
||||
|
|
@ -30,7 +30,7 @@ fn main() {
|
|||
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();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
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},
|
||||
};
|
||||
|
||||
|
|
@ -75,19 +78,19 @@ fn main() {
|
|||
// setup the multiplexer by specifying the bearer and the IDs of the
|
||||
// miniprotocols to use
|
||||
let mut plexer = multiplexer::StdPlexer::new(bearer);
|
||||
let channel0 = plexer.use_channel(0);
|
||||
let channel7 = plexer.use_channel(7);
|
||||
let channel5 = plexer.use_channel(5);
|
||||
let handshake = plexer.use_channel(PROTOCOL_N2C_HANDSHAKE);
|
||||
let statequery = plexer.use_channel(PROTOCOL_N2C_STATE_QUERY);
|
||||
let chainsync = plexer.use_channel(PROTOCOL_N2C_CHAIN_SYNC);
|
||||
|
||||
plexer.muxer.spawn();
|
||||
plexer.demuxer.spawn();
|
||||
|
||||
// execute the required handshake against the relay
|
||||
do_handshake(channel0);
|
||||
do_handshake(handshake);
|
||||
|
||||
// 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
|
||||
do_chainsync(channel5);
|
||||
do_chainsync(chainsync);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
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},
|
||||
};
|
||||
|
||||
|
|
@ -83,19 +86,19 @@ fn main() {
|
|||
// setup the multiplexer by specifying the bearer and the IDs of the
|
||||
// miniprotocols to use
|
||||
let mut plexer = StdPlexer::new(bearer);
|
||||
let channel0 = plexer.use_channel(0);
|
||||
let channel3 = plexer.use_channel(3);
|
||||
let channel2 = plexer.use_channel(2);
|
||||
let handshake = plexer.use_channel(PROTOCOL_N2N_HANDSHAKE);
|
||||
let blockfetch = plexer.use_channel(PROTOCOL_N2N_BLOCK_FETCH);
|
||||
let chainsync = plexer.use_channel(PROTOCOL_N2N_CHAIN_SYNC);
|
||||
|
||||
plexer.muxer.spawn();
|
||||
plexer.demuxer.spawn();
|
||||
|
||||
// execute the required handshake against the relay
|
||||
do_handshake(channel0);
|
||||
do_handshake(handshake);
|
||||
|
||||
// fetch an arbitrary batch of block
|
||||
do_blockfetch(channel3);
|
||||
do_blockfetch(blockfetch);
|
||||
|
||||
// execute the chainsync flow from an arbitrary point in the chain
|
||||
do_chainsync(channel2);
|
||||
do_chainsync(chainsync);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
//!
|
||||
//! However, only the [`SecretKeyExtended`] can be used for HD derivation
|
||||
//! (using [ed25519_bip32] or otherwise).
|
||||
//!
|
||||
|
||||
use crate::memsec::Scrubbed as _;
|
||||
use cryptoxide::ed25519::{
|
||||
|
|
@ -18,13 +17,13 @@ use std::{any::type_name, convert::TryFrom, fmt, str::FromStr};
|
|||
use thiserror::Error;
|
||||
|
||||
/// Ed25519 Secret Key
|
||||
///
|
||||
#[derive(Clone)]
|
||||
pub struct SecretKey([u8; Self::SIZE]);
|
||||
|
||||
/// 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)]
|
||||
pub struct SecretKeyExtended([u8; Self::SIZE]);
|
||||
|
||||
|
|
@ -77,7 +76,6 @@ impl_size_zero!(Signature, SIGNATURE_LENGTH);
|
|||
|
||||
impl SecretKey {
|
||||
/// generate a new [`SecretKey`] with the given random number generator
|
||||
///
|
||||
pub fn new<Rng>(mut rng: Rng) -> Self
|
||||
where
|
||||
Rng: RngCore + CryptoRng,
|
||||
|
|
@ -106,8 +104,8 @@ impl SecretKey {
|
|||
|
||||
/// create a [`Signature`] for the given message with this [`SecretKey`].
|
||||
///
|
||||
/// The [`Signature`] can then be verified against the associated [`PublicKey`]
|
||||
/// and the original message.
|
||||
/// The [`Signature`] can then be verified against the associated
|
||||
/// [`PublicKey`] and the original message.
|
||||
pub fn sign<T>(&self, msg: T) -> Signature
|
||||
where
|
||||
T: AsRef<[u8]>,
|
||||
|
|
@ -125,8 +123,8 @@ impl SecretKey {
|
|||
}
|
||||
|
||||
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
|
||||
where
|
||||
Rng: RngCore + CryptoRng,
|
||||
|
|
@ -180,7 +178,6 @@ impl SecretKeyExtended {
|
|||
impl PublicKey {
|
||||
/// verify the cryptographic [`Signature`] against the `message` and the
|
||||
/// [`PublicKey`] `self`.
|
||||
///
|
||||
#[inline]
|
||||
pub fn verify<T>(&self, message: T, signature: &Signature) -> bool
|
||||
where
|
||||
|
|
@ -438,11 +435,12 @@ mod tests {
|
|||
signature: Signature,
|
||||
message: Vec<u8>,
|
||||
) -> bool {
|
||||
// NOTE: this test may fail but it is impossible to see this happening in normal condition.
|
||||
// we are generating 32 random bytes of public key and 64 random bytes
|
||||
// of signature with an randomly generated message of a random number
|
||||
// of bytes in. If the message were empty, the probability to have
|
||||
// a signature that matches the verify key would still be 1 out of 2^96.
|
||||
// NOTE: this test may fail but it is impossible to see this happening in normal
|
||||
// condition. we are generating 32 random bytes of public key and
|
||||
// 64 random bytes of signature with an randomly generated message
|
||||
// of a random number of bytes in. If the message were empty, the
|
||||
// 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.
|
||||
!public_key.verify(message, &signature)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@ homepage = "https://github.com/txpipe/pallas"
|
|||
documentation = "https://docs.rs/pallas-machines"
|
||||
license = "Apache-2.0"
|
||||
readme = "README.md"
|
||||
authors = ["Santiago Carmuega <santiago@carmuega.me>"]
|
||||
authors = [
|
||||
"Santiago Carmuega <santiago@carmuega.me>",
|
||||
"Pi Lanningham <pi.lanningham@gmail.com>"
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
pallas-codec = { version = "0.18.0", path = "../pallas-codec/" }
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ bearer.set_keepalive_ms(Some(30_000u32)).unwrap();
|
|||
let mut muxer = Multiplexer::setup(bearer, &[0]).unwrap();
|
||||
|
||||
// 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
|
||||
let agent = handshake::Client::initial(VersionTable::v4_and_above(MAINNET_MAGIC));
|
||||
|
|
|
|||
|
|
@ -14,6 +14,33 @@ pub const PREVIEW_MAGIC: u64 = 2;
|
|||
/// Well-known magic for pre-production
|
||||
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
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
pub enum Point {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ where
|
|||
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 {
|
||||
!matches!(self.state(), State::Idle)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ where
|
|||
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 {
|
||||
matches!(self.state(), State::Idle)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,29 +3,30 @@ use pallas_miniprotocols::{
|
|||
chainsync::{self, NextResponse},
|
||||
handshake::{self, Confirmation},
|
||||
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};
|
||||
|
||||
struct N2NChannels {
|
||||
channel2: StdChannel,
|
||||
channel3: StdChannel,
|
||||
channel4: StdChannel,
|
||||
chainsync: StdChannel,
|
||||
blockfetch: StdChannel,
|
||||
txsubmission: StdChannel,
|
||||
}
|
||||
|
||||
fn setup_n2n_client_connection() -> N2NChannels {
|
||||
let bearer = Bearer::connect_tcp("preview-node.world.dev.cardano.org:30002").unwrap();
|
||||
let mut plexer = StdPlexer::new(bearer);
|
||||
|
||||
let channel0 = plexer.use_channel(0);
|
||||
let channel2 = plexer.use_channel(2);
|
||||
let channel3 = plexer.use_channel(3);
|
||||
let channel4 = plexer.use_channel(4);
|
||||
let handshake = plexer.use_channel(PROTOCOL_N2N_HANDSHAKE);
|
||||
let chainsync = plexer.use_channel(PROTOCOL_N2N_CHAIN_SYNC);
|
||||
let blockfetch = plexer.use_channel(PROTOCOL_N2N_BLOCK_FETCH);
|
||||
let txsubmission = plexer.use_channel(PROTOCOL_N2N_TX_SUBMISSION);
|
||||
|
||||
plexer.muxer.spawn();
|
||||
plexer.demuxer.spawn();
|
||||
|
||||
let mut client = handshake::N2NClient::new(channel0);
|
||||
let mut client = handshake::N2NClient::new(handshake);
|
||||
|
||||
let confirmation = client
|
||||
.handshake(handshake::n2n::VersionTable::v7_and_above(2))
|
||||
|
|
@ -38,23 +39,23 @@ fn setup_n2n_client_connection() -> N2NChannels {
|
|||
}
|
||||
|
||||
N2NChannels {
|
||||
channel2,
|
||||
channel3,
|
||||
channel4,
|
||||
chainsync,
|
||||
blockfetch,
|
||||
txsubmission,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
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(
|
||||
1654413,
|
||||
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();
|
||||
|
||||
|
|
@ -93,9 +94,9 @@ pub fn chainsync_history_happy_path() {
|
|||
#[test]
|
||||
#[ignore]
|
||||
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();
|
||||
|
||||
|
|
@ -132,14 +133,14 @@ pub fn chainsync_tip_happy_path() {
|
|||
#[test]
|
||||
#[ignore]
|
||||
pub fn blockfetch_happy_path() {
|
||||
let N2NChannels { channel3, .. } = setup_n2n_client_connection();
|
||||
let N2NChannels { blockfetch, .. } = setup_n2n_client_connection();
|
||||
|
||||
let known_point = Point::Specific(
|
||||
1654413,
|
||||
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()));
|
||||
|
||||
|
|
@ -170,13 +171,14 @@ pub fn blockfetch_happy_path() {
|
|||
#[test]
|
||||
#[ignore]
|
||||
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
|
||||
// which seems awkward;
|
||||
// Alternatively, we can just set up both a client and server connecting to themselves for testing!
|
||||
// TODO(pi): Note that the below doesn't work; we need a node to connect *to us*
|
||||
// during the integration test which seems awkward;
|
||||
// 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(_)));
|
||||
|
||||
|
|
@ -209,7 +211,8 @@ pub fn txsubmission_server_happy_path() {
|
|||
assert!(matches!(reply, Ok(Reply::Txs(_))));
|
||||
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[1], first_txs[2]);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,13 +34,13 @@ let bearer = UnixStream::connect("/tmp/pallas").unwrap();
|
|||
let muxer = Multiplexer::setup(tcp, &[0, 2])
|
||||
|
||||
// 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.
|
||||
thread::spawn(move || {
|
||||
// Deconstruct the channel to get a handle for sending data into the muxer
|
||||
// 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
|
||||
// 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.
|
||||
let mut channel_2 = muxer.use_channel(2);
|
||||
// Ask the multiplexer to provide us with the channel for the chainsync miniprotocol.
|
||||
let mut chainsync = muxer.use_channel(PROTOCOL_N2N_CHAINSYNC);
|
||||
|
||||
// Spawn a different thread and pass the ownership of the 2nd channel.
|
||||
thread::spawn(move || {
|
||||
// Deconstruct the channel to get a handle for sending data into the muxer
|
||||
// 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
|
||||
// whatever get received for this mini-protocol.
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
#[serde(into = "String")]
|
||||
#[serde(try_from = "String")]
|
||||
|
|
@ -899,7 +900,8 @@ impl<C> Encode<C> for BoundedBytes {
|
|||
e: &mut minicbor::Encoder<W>,
|
||||
_: &mut C,
|
||||
) -> 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;
|
||||
let bs: &Vec<u8> = self.deref();
|
||||
if bs.len() <= 64 {
|
||||
|
|
@ -1086,8 +1088,8 @@ impl<C> minicbor::encode::Encode<C> for PlutusData {
|
|||
e.encode_with(a, ctx)?;
|
||||
}
|
||||
Self::Map(a) => {
|
||||
// we use definite array to match the approach used by haskell's plutus implementation
|
||||
// https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L152
|
||||
// we use definite array to match the approach used by haskell's plutus
|
||||
// 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())?;
|
||||
for (k, v) in a.iter() {
|
||||
k.encode(e, ctx)?;
|
||||
|
|
@ -1101,8 +1103,8 @@ impl<C> minicbor::encode::Encode<C> for PlutusData {
|
|||
e.encode_with(a, ctx)?;
|
||||
}
|
||||
Self::Array(a) => {
|
||||
// we use definite array for empty array or indef array otherwise to match haskell implementation
|
||||
// https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L153
|
||||
// we use definite array for empty array or indef array otherwise to match
|
||||
// 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:
|
||||
// https://github.com/well-typed/cborg/blob/4bdc818a1f0b35f38bc118a87944630043b58384/serialise/src/Codec/Serialise/Class.hs#L181
|
||||
encode_list(a, e, ctx)?;
|
||||
|
|
@ -1172,15 +1174,16 @@ where
|
|||
e.array(2)?;
|
||||
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
|
||||
// https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L144
|
||||
// we use definite array for empty array or indef array otherwise to match
|
||||
// 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:
|
||||
// https://github.com/well-typed/cborg/blob/4bdc818a1f0b35f38bc118a87944630043b58384/serialise/src/Codec/Serialise/Class.hs#L181
|
||||
encode_list(&self.fields, e, ctx)?;
|
||||
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)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
/// 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
|
||||
/// collateral return if one is present or an empty list if not. Note that the
|
||||
/// collateral return output index is defined as the next available index after
|
||||
/// the txouts (Babbage spec, ch 4).
|
||||
/// collateral return if one is present or an empty list if not. Note that
|
||||
/// the collateral return output index is defined as the next available
|
||||
/// index after the txouts (Babbage spec, ch 4).
|
||||
pub fn produces(&self) -> Vec<(usize, MultiEraOutput)> {
|
||||
match self.is_valid() {
|
||||
true => self.outputs().into_iter().enumerate().collect(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue