feat: introduce conway primitives (#290)
Co-authored-by: lisicky <lisicky@inbox.ru>
This commit is contained in:
parent
2b5f22def2
commit
93c978b0e3
19 changed files with 2419 additions and 34 deletions
|
|
@ -1,5 +1,5 @@
|
|||
use thiserror::Error;
|
||||
use tracing::{debug, info, warn};
|
||||
use tracing::{debug, warn};
|
||||
|
||||
use crate::miniprotocols::common::Point;
|
||||
use crate::multiplexer;
|
||||
|
|
@ -138,7 +138,7 @@ impl Client {
|
|||
pub async fn recv_while_busy(&mut self) -> Result<HasBlocks, ClientError> {
|
||||
match self.recv_message().await? {
|
||||
Message::StartBatch => {
|
||||
info!("batch start");
|
||||
debug!("batch start");
|
||||
self.0 = State::Streaming;
|
||||
Ok(Some(()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! Ledger primitives and cbor codec for the Alonzo era
|
||||
//! Ledger primitives and cbor codec for the Babbage era
|
||||
//!
|
||||
//! Handcrafted, idiomatic rust artifacts based on based on the [Babbage CDDL](https://github.com/input-output-hk/cardano-ledger/blob/master/eras/babbage/test-suite/cddl-files/babbage.cddl) file in IOHK repo.
|
||||
|
||||
|
|
|
|||
594
pallas-primitives/src/conway/defs.cddl
Normal file
594
pallas-primitives/src/conway/defs.cddl
Normal file
|
|
@ -0,0 +1,594 @@
|
|||
; fetched 11 sep 2023
|
||||
|
||||
block =
|
||||
[ header
|
||||
, transaction_bodies : [* transaction_body]
|
||||
, transaction_witness_sets : [* transaction_witness_set]
|
||||
, auxiliary_data_set : {* transaction_index => auxiliary_data }
|
||||
, invalid_transactions : [* transaction_index ]
|
||||
]; Valid blocks must also satisfy the following two constraints:
|
||||
; 1) the length of transaction_bodies and transaction_witness_sets
|
||||
; must be the same
|
||||
; 2) every transaction_index must be strictly smaller than the
|
||||
; length of transaction_bodies
|
||||
|
||||
transaction =
|
||||
[ transaction_body
|
||||
, transaction_witness_set
|
||||
, bool
|
||||
, auxiliary_data / null
|
||||
]
|
||||
|
||||
transaction_index = uint .size 2
|
||||
|
||||
header =
|
||||
[ header_body
|
||||
, body_signature : $kes_signature
|
||||
]
|
||||
|
||||
header_body =
|
||||
[ block_number : uint
|
||||
, slot : uint
|
||||
, prev_hash : $hash32 / null
|
||||
, issuer_vkey : $vkey
|
||||
, vrf_vkey : $vrf_vkey
|
||||
, vrf_result : $vrf_cert ; replaces nonce_vrf and leader_vrf
|
||||
, block_body_size : uint
|
||||
, block_body_hash : $hash32 ; merkle triple root
|
||||
, operational_cert
|
||||
, protocol_version
|
||||
]
|
||||
|
||||
operational_cert =
|
||||
( hot_vkey : $kes_vkey
|
||||
, sequence_number : uint
|
||||
, kes_period : uint
|
||||
, sigma : $signature
|
||||
)
|
||||
|
||||
next_major_protocol_version = 10
|
||||
|
||||
major_protocol_version = 1..next_major_protocol_version
|
||||
|
||||
protocol_version = (major_protocol_version, uint)
|
||||
|
||||
transaction_body =
|
||||
{ 0 : set<transaction_input> ; inputs
|
||||
, 1 : [* transaction_output]
|
||||
, 2 : coin ; fee
|
||||
, ? 3 : uint ; time to live
|
||||
, ? 4 : [+ certificate]
|
||||
, ? 5 : withdrawals
|
||||
, ? 7 : auxiliary_data_hash
|
||||
, ? 8 : uint ; validity interval start
|
||||
, ? 9 : mint
|
||||
, ? 11 : script_data_hash
|
||||
, ? 13 : nonempty_set<transaction_input> ; collateral inputs
|
||||
, ? 14 : required_signers
|
||||
, ? 15 : network_id
|
||||
, ? 16 : transaction_output ; collateral return
|
||||
, ? 17 : coin ; total collateral
|
||||
, ? 18 : nonempty_set<transaction_input> ; reference inputs
|
||||
, ? 19 : voting_procedures ; New; Voting procedures
|
||||
, ? 20 : [+ proposal_procedure] ; New; Proposal procedures
|
||||
, ? 21 : coin ; New; current treasury value
|
||||
, ? 22 : positive_coin ; New; donation
|
||||
}
|
||||
|
||||
voting_procedures = { + voter => { + gov_action_id => voting_procedure } }
|
||||
|
||||
voting_procedure =
|
||||
[ vote
|
||||
, anchor / null
|
||||
]
|
||||
|
||||
proposal_procedure =
|
||||
[ deposit : coin
|
||||
, reward_account
|
||||
, gov_action
|
||||
, anchor
|
||||
]
|
||||
|
||||
gov_action =
|
||||
[ parameter_change_action
|
||||
// hard_fork_initiation_action
|
||||
// treasury_withdrawals_action
|
||||
// no_confidence
|
||||
// new_committee
|
||||
// new_constitution
|
||||
// info_action
|
||||
]
|
||||
|
||||
parameter_change_action = (0, gov_action_id / null, protocol_param_update)
|
||||
|
||||
hard_fork_initiation_action = (1, gov_action_id / null, [protocol_version])
|
||||
|
||||
treasury_withdrawals_action = (2, { $reward_account => coin })
|
||||
|
||||
no_confidence = (3, gov_action_id / null)
|
||||
|
||||
new_committee = (4, gov_action_id / null, set<$committee_cold_credential>, committee)
|
||||
|
||||
new_constitution = (5, gov_action_id / null, constitution)
|
||||
|
||||
committee = [{ $committee_cold_credential => epoch }, unit_interval]
|
||||
|
||||
constitution =
|
||||
[ anchor
|
||||
, scripthash / null
|
||||
]
|
||||
|
||||
info_action = 6
|
||||
|
||||
; Constitutional Committee Hot KeyHash: 0
|
||||
; Constitutional Committee Hot ScriptHash: 1
|
||||
; DRep KeyHash: 2
|
||||
; DRep ScriptHash: 3
|
||||
; StakingPool KeyHash: 4
|
||||
voter =
|
||||
[ 0, addr_keyhash
|
||||
// 1, scripthash
|
||||
// 2, addr_keyhash
|
||||
// 3, scripthash
|
||||
// 4, addr_keyhash
|
||||
]
|
||||
|
||||
anchor =
|
||||
[ anchor_url : url
|
||||
, anchor_data_hash : $hash32
|
||||
]
|
||||
|
||||
; no - 0
|
||||
; yes - 1
|
||||
; abstain - 2
|
||||
vote = 0 .. 2
|
||||
|
||||
gov_action_id =
|
||||
[ transaction_id : $hash32
|
||||
, gov_action_index : uint
|
||||
]
|
||||
|
||||
required_signers = nonempty_set<$addr_keyhash>
|
||||
|
||||
transaction_input = [ transaction_id : $hash32
|
||||
, index : uint
|
||||
]
|
||||
|
||||
transaction_output = legacy_transaction_output / post_alonzo_transaction_output
|
||||
|
||||
legacy_transaction_output =
|
||||
[ address
|
||||
, amount : value
|
||||
, ? datum_hash : $hash32
|
||||
]
|
||||
|
||||
post_alonzo_transaction_output =
|
||||
{ 0 : address
|
||||
, 1 : value
|
||||
, ? 2 : datum_option ; datum option
|
||||
, ? 3 : script_ref ; script reference
|
||||
}
|
||||
|
||||
script_data_hash = $hash32
|
||||
; This is a hash of data which may affect evaluation of a script.
|
||||
; This data consists of:
|
||||
; - The redeemers from the transaction_witness_set (the value of field 5).
|
||||
; - The datums from the transaction_witness_set (the value of field 4).
|
||||
; - The value in the costmdls map corresponding to the script's language
|
||||
; (in field 18 of protocol_param_update.)
|
||||
; (In the future it may contain additional protocol parameters.)
|
||||
;
|
||||
; Since this data does not exist in contiguous form inside a transaction, it needs
|
||||
; to be independently constructed by each recipient.
|
||||
;
|
||||
; The bytestring which is hashed is the concatenation of three things:
|
||||
; redeemers || datums || language views
|
||||
; The redeemers are exactly the data present in the transaction witness set.
|
||||
; Similarly for the datums, if present. If no datums are provided, the middle
|
||||
; field is omitted (i.e. it is the empty/null bytestring).
|
||||
;
|
||||
; language views CDDL:
|
||||
; { * language => script_integrity_data }
|
||||
;
|
||||
; This must be encoded canonically, using the same scheme as in
|
||||
; RFC7049 section 3.9:
|
||||
; - Maps, strings, and bytestrings must use a definite-length encoding
|
||||
; - Integers must be as small as possible.
|
||||
; - The expressions for map length, string length, and bytestring length
|
||||
; must be as short as possible.
|
||||
; - The keys in the map must be sorted as follows:
|
||||
; - If two keys have different lengths, the shorter one sorts earlier.
|
||||
; - If two keys have the same length, the one with the lower value
|
||||
; in (byte-wise) lexical order sorts earlier.
|
||||
;
|
||||
; For PlutusV1 (language id 0), the language view is the following:
|
||||
; - the value of costmdls map at key 0 (in other words, the script_integrity_data)
|
||||
; is encoded as an indefinite length list and the result is encoded as a bytestring.
|
||||
; (our apologies)
|
||||
; For example, the script_integrity_data corresponding to the all zero costmodel for V1
|
||||
; would be encoded as (in hex):
|
||||
; 58a89f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff
|
||||
; - the language ID tag is also encoded twice. first as a uint then as
|
||||
; a bytestring. (our apologies)
|
||||
; Concretely, this means that the language version for V1 is encoded as
|
||||
; 4100 in hex.
|
||||
; For PlutusV2 (language id 1), the language view is the following:
|
||||
; - the value of costmdls map at key 1 is encoded as an definite length list.
|
||||
; For example, the script_integrity_data corresponding to the all zero costmodel for V2
|
||||
; would be encoded as (in hex):
|
||||
; 98af0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
; - the language ID tag is encoded as expected.
|
||||
; Concretely, this means that the language version for V2 is encoded as
|
||||
; 01 in hex.
|
||||
; For PlutusV3 (language id 2), the language view is the following:
|
||||
; - the value of costmdls map at key 2 is encoded as a definite length list.
|
||||
;
|
||||
; Note that each Plutus language represented inside a transaction must have
|
||||
; a cost model in the costmdls protocol parameter in order to execute,
|
||||
; regardless of what the script integrity data is.
|
||||
;
|
||||
; Finally, note that in the case that a transaction includes datums but does not
|
||||
; include the redeemers field, the script data format becomes (in hex):
|
||||
; [ 80 | datums | A0 ]
|
||||
; corresponding to a CBOR empty list and an empty map.
|
||||
; Note that a transaction might include the redeemers field and it to the
|
||||
; empty map, in which case the user supplied encoding of the empty map is used.
|
||||
|
||||
; address = bytes
|
||||
; reward_account = bytes
|
||||
|
||||
; address format:
|
||||
; [ 8 bit header | payload ];
|
||||
;
|
||||
; shelley payment addresses:
|
||||
; bit 7: 0
|
||||
; bit 6: base/other
|
||||
; bit 5: pointer/enterprise [for base: stake cred is keyhash/scripthash]
|
||||
; bit 4: payment cred is keyhash/scripthash
|
||||
; bits 3-0: network id
|
||||
;
|
||||
; reward addresses:
|
||||
; bits 7-5: 111
|
||||
; bit 4: credential is keyhash/scripthash
|
||||
; bits 3-0: network id
|
||||
;
|
||||
; byron addresses:
|
||||
; bits 7-4: 1000
|
||||
|
||||
; 0000: base address: keyhash28,keyhash28
|
||||
; 0001: base address: scripthash28,keyhash28
|
||||
; 0010: base address: keyhash28,scripthash28
|
||||
; 0011: base address: scripthash28,scripthash28
|
||||
; 0100: pointer address: keyhash28, 3 variable length uint
|
||||
; 0101: pointer address: scripthash28, 3 variable length uint
|
||||
; 0110: enterprise address: keyhash28
|
||||
; 0111: enterprise address: scripthash28
|
||||
; 1000: byron address
|
||||
; 1110: reward account: keyhash28
|
||||
; 1111: reward account: scripthash28
|
||||
; 1001 - 1101: future formats
|
||||
|
||||
certificate =
|
||||
[ stake_registration
|
||||
// stake_deregistration
|
||||
// stake_delegation
|
||||
// pool_registration
|
||||
// pool_retirement
|
||||
// reg_cert
|
||||
// unreg_cert
|
||||
// vote_deleg_cert
|
||||
// stake_vote_deleg_cert
|
||||
// stake_reg_deleg_cert
|
||||
// vote_reg_deleg_cert
|
||||
// stake_vote_reg_deleg_cert
|
||||
// auth_committee_hot_cert
|
||||
// resign_committee_cold_cert
|
||||
// reg_drep_cert
|
||||
// unreg_drep_cert
|
||||
// update_drep_cert
|
||||
]
|
||||
|
||||
stake_registration = (0, stake_credential) ; to be deprecated in era after Conway
|
||||
stake_deregistration = (1, stake_credential) ; to be deprecated in era after Conway
|
||||
stake_delegation = (2, stake_credential, pool_keyhash)
|
||||
|
||||
; POOL
|
||||
pool_registration = (3, pool_params)
|
||||
pool_retirement = (4, pool_keyhash, epoch)
|
||||
|
||||
; numbers 5 and 6 used to be the Genesis and MIR certificates respectively,
|
||||
; which were deprecated in Conway
|
||||
|
||||
; DELEG
|
||||
reg_cert = (7, stake_credential, coin)
|
||||
unreg_cert = (8, stake_credential, coin)
|
||||
vote_deleg_cert = (9, stake_credential, drep)
|
||||
stake_vote_deleg_cert = (10, stake_credential, pool_keyhash, drep)
|
||||
stake_reg_deleg_cert = (11, stake_credential, pool_keyhash, coin)
|
||||
vote_reg_deleg_cert = (12, stake_credential, drep, coin)
|
||||
stake_vote_reg_deleg_cert = (13, stake_credential, pool_keyhash, drep, coin)
|
||||
|
||||
; GOVCERT
|
||||
auth_committee_hot_cert = (14, committee_cold_credential, committee_hot_credential)
|
||||
resign_committee_cold_cert = (15, committee_cold_credential)
|
||||
reg_drep_cert = (16, drep_credential, coin, anchor / null)
|
||||
unreg_drep_cert = (17, drep_credential, coin)
|
||||
update_drep_cert = (18, drep_credential, anchor / null)
|
||||
|
||||
|
||||
delta_coin = int
|
||||
|
||||
credential =
|
||||
[ 0, addr_keyhash
|
||||
// 1, scripthash
|
||||
]
|
||||
|
||||
drep =
|
||||
[ 0, addr_keyhash
|
||||
// 1, scripthash
|
||||
// 2 ; always abstain
|
||||
// 3 ; always no confidence
|
||||
]
|
||||
|
||||
stake_credential = credential
|
||||
drep_credential = credential
|
||||
committee_cold_credential = credential
|
||||
committee_hot_credential = credential
|
||||
|
||||
pool_params = ( operator: pool_keyhash
|
||||
, vrf_keyhash: vrf_keyhash
|
||||
, pledge: coin
|
||||
, cost: coin
|
||||
, margin: unit_interval
|
||||
, reward_account: reward_account
|
||||
, pool_owners: set<addr_keyhash>
|
||||
, relays: [* relay]
|
||||
, pool_metadata: pool_metadata / null
|
||||
)
|
||||
|
||||
port = uint .le 65535
|
||||
ipv4 = bytes .size 4
|
||||
ipv6 = bytes .size 16
|
||||
dns_name = tstr .size (0..64)
|
||||
|
||||
single_host_addr = ( 0
|
||||
, port / null
|
||||
, ipv4 / null
|
||||
, ipv6 / null
|
||||
)
|
||||
single_host_name = ( 1
|
||||
, port / null
|
||||
, dns_name ; An A or AAAA DNS record
|
||||
)
|
||||
multi_host_name = ( 2
|
||||
, dns_name ; A SRV DNS record
|
||||
)
|
||||
relay =
|
||||
[ single_host_addr
|
||||
// single_host_name
|
||||
// multi_host_name
|
||||
]
|
||||
|
||||
pool_metadata = [url, pool_metadata_hash]
|
||||
url = tstr .size (0..64)
|
||||
|
||||
withdrawals = { + reward_account => coin }
|
||||
|
||||
protocol_param_update =
|
||||
{ ? 0: uint ; minfee A
|
||||
, ? 1: uint ; minfee B
|
||||
, ? 2: uint ; max block body size
|
||||
, ? 3: uint ; max transaction size
|
||||
, ? 4: uint ; max block header size
|
||||
, ? 5: coin ; key deposit
|
||||
, ? 6: coin ; pool deposit
|
||||
, ? 7: epoch ; maximum epoch
|
||||
, ? 8: uint ; n_opt: desired number of stake pools
|
||||
, ? 9: rational ; pool pledge influence
|
||||
, ? 10: unit_interval ; expansion rate
|
||||
, ? 11: unit_interval ; treasury growth rate
|
||||
, ? 16: coin ; min pool cost
|
||||
, ? 17: coin ; ada per utxo byte
|
||||
, ? 18: costmdls ; cost models for script languages
|
||||
, ? 19: ex_unit_prices ; execution costs
|
||||
, ? 20: ex_units ; max tx ex units
|
||||
, ? 21: ex_units ; max block ex units
|
||||
, ? 22: uint ; max value size
|
||||
, ? 23: uint ; collateral percentage
|
||||
, ? 24: uint ; max collateral inputs
|
||||
, ? 25: pool_voting_thresholds ; pool voting thresholds
|
||||
, ? 26: drep_voting_thresholds ; DRep voting thresholds
|
||||
, ? 27: uint ; min committee size
|
||||
, ? 28: uint ; committee term limit
|
||||
, ? 29: epoch ; governance action validity period
|
||||
, ? 30: coin ; governance action deposit
|
||||
, ? 31: coin ; DRep deposit
|
||||
, ? 32: epoch ; DRep inactivity period
|
||||
}
|
||||
|
||||
pool_voting_thresholds =
|
||||
[ unit_interval ; motion no confidence
|
||||
, unit_interval ; committee normal
|
||||
, unit_interval ; committee no confidence
|
||||
, unit_interval ; hard fork initiation
|
||||
]
|
||||
|
||||
drep_voting_thresholds =
|
||||
[ unit_interval ; motion no confidence
|
||||
, unit_interval ; committee normal
|
||||
, unit_interval ; committee no confidence
|
||||
, unit_interval ; update constitution
|
||||
, unit_interval ; hard fork initiation
|
||||
, unit_interval ; PP network group
|
||||
, unit_interval ; PP economic group
|
||||
, unit_interval ; PP technical group
|
||||
, unit_interval ; PP governance group
|
||||
, unit_interval ; treasury withdrawal
|
||||
]
|
||||
|
||||
transaction_witness_set =
|
||||
{ ? 0: [* vkeywitness ]
|
||||
, ? 1: [* native_script ]
|
||||
, ? 2: [* bootstrap_witness ]
|
||||
, ? 3: [* plutus_v1_script ]
|
||||
, ? 4: [* plutus_data ]
|
||||
, ? 5: [* redeemer ]
|
||||
, ? 6: [* plutus_v2_script ]
|
||||
, ? 7: [* plutus_v3_script ]
|
||||
}
|
||||
|
||||
plutus_v1_script = bytes
|
||||
plutus_v2_script = bytes
|
||||
plutus_v3_script = bytes
|
||||
|
||||
plutus_data =
|
||||
constr<plutus_data>
|
||||
/ { * plutus_data => plutus_data }
|
||||
/ [ * plutus_data ]
|
||||
/ big_int
|
||||
/ bounded_bytes
|
||||
|
||||
big_int = int / big_uint / big_nint
|
||||
big_uint = #6.2(bounded_bytes)
|
||||
big_nint = #6.3(bounded_bytes)
|
||||
|
||||
constr<a> =
|
||||
#6.121([* a])
|
||||
/ #6.122([* a])
|
||||
/ #6.123([* a])
|
||||
/ #6.124([* a])
|
||||
/ #6.125([* a])
|
||||
/ #6.126([* a])
|
||||
/ #6.127([* a])
|
||||
; similarly for tag range: 6.1280 .. 6.1400 inclusive
|
||||
/ #6.102([uint, [* a]])
|
||||
|
||||
redeemer = [ tag: redeemer_tag, index: uint, data: plutus_data, ex_units: ex_units ]
|
||||
redeemer_tag =
|
||||
0 ; inputTag "Spend"
|
||||
/ 1 ; mintTag "Mint"
|
||||
/ 2 ; certTag "Cert"
|
||||
/ 3 ; wdrlTag "Reward"
|
||||
; TODO / 4 ; drepTag "DRep"
|
||||
ex_units = [mem: uint, steps: uint]
|
||||
|
||||
ex_unit_prices =
|
||||
[ mem_price: sub_coin, step_price: sub_coin ]
|
||||
|
||||
language = 0 ; Plutus v1
|
||||
/ 1 ; Plutus v2
|
||||
/ 2 ; Plutus v3
|
||||
|
||||
potential_languages = 0 .. 255
|
||||
|
||||
; The format for costmdls is flexible enough to allow adding Plutus built-ins and language
|
||||
; versions in the future.
|
||||
;
|
||||
; To construct valid cost models, however, you must restrict to:
|
||||
;
|
||||
; { ? 0 : [ 166* int ] ; Plutus v1, only 166 integers are used, but more are accepted (and ignored)
|
||||
; , ? 1 : [ 175* int ] ; Plutus v2, only 175 integers are used, but more are accepted (and ignored)
|
||||
; , ? 2 : [ 179* int ] ; Plutus v3, only 179 integers are used, but more are accepted (and ignored)
|
||||
; }
|
||||
costmdls = { * potential_languages => [int] }
|
||||
|
||||
transaction_metadatum =
|
||||
{ * transaction_metadatum => transaction_metadatum }
|
||||
/ [ * transaction_metadatum ]
|
||||
/ int
|
||||
/ bytes .size (0..64)
|
||||
/ text .size (0..64)
|
||||
|
||||
transaction_metadatum_label = uint
|
||||
metadata = { * transaction_metadatum_label => transaction_metadatum }
|
||||
|
||||
auxiliary_data =
|
||||
metadata ; Shelley
|
||||
/ [ transaction_metadata: metadata ; Shelley-ma
|
||||
, auxiliary_scripts: [ * native_script ]
|
||||
]
|
||||
/ #6.259({ ? 0 => metadata ; Alonzo and beyond
|
||||
, ? 1 => [ * native_script ]
|
||||
, ? 2 => [ * plutus_v1_script ]
|
||||
, ? 3 => [ * plutus_v2_script ]
|
||||
, ? 4 => [ * plutus_v3_script ]
|
||||
})
|
||||
|
||||
vkeywitness = [ $vkey, $signature ]
|
||||
|
||||
bootstrap_witness =
|
||||
[ public_key : $vkey
|
||||
, signature : $signature
|
||||
, chain_code : bytes .size 32
|
||||
, attributes : bytes
|
||||
]
|
||||
|
||||
native_script =
|
||||
[ script_pubkey
|
||||
// script_all
|
||||
// script_any
|
||||
// script_n_of_k
|
||||
// invalid_before
|
||||
; Timelock validity intervals are half-open intervals [a, b).
|
||||
; This field specifies the left (included) endpoint a.
|
||||
// invalid_hereafter
|
||||
; Timelock validity intervals are half-open intervals [a, b).
|
||||
; This field specifies the right (excluded) endpoint b.
|
||||
]
|
||||
|
||||
script_pubkey = (0, addr_keyhash)
|
||||
script_all = (1, [ * native_script ])
|
||||
script_any = (2, [ * native_script ])
|
||||
script_n_of_k = (3, n: uint, [ * native_script ])
|
||||
invalid_before = (4, uint)
|
||||
invalid_hereafter = (5, uint)
|
||||
|
||||
coin = uint
|
||||
|
||||
sub_coin = positive_interval
|
||||
|
||||
multiasset<a> = { + policy_id => { + asset_name => a } }
|
||||
policy_id = scripthash
|
||||
asset_name = bytes .size (0..32)
|
||||
|
||||
negInt64 = -9223372036854775808 .. -1
|
||||
posInt64 = 1 .. 9223372036854775807
|
||||
nonZeroInt64 = negInt64 / posInt64 ; this is the same as the current int64 definition but without zero
|
||||
|
||||
positive_coin = 1 .. 18446744073709551615
|
||||
|
||||
value = positive_coin / [positive_coin,multiasset<positive_coin>]
|
||||
|
||||
mint = multiasset<nonZeroInt64>
|
||||
|
||||
int64 = -9223372036854775808 .. 9223372036854775807
|
||||
|
||||
network_id = 0 / 1
|
||||
|
||||
epoch = uint
|
||||
|
||||
addr_keyhash = $hash28
|
||||
pool_keyhash = $hash28
|
||||
|
||||
vrf_keyhash = $hash32
|
||||
auxiliary_data_hash = $hash32
|
||||
pool_metadata_hash = $hash32
|
||||
|
||||
; To compute a script hash, note that you must prepend
|
||||
; a tag to the bytes of the script before hashing.
|
||||
; The tag is determined by the language.
|
||||
; The tags in the Conway era are:
|
||||
; "\x00" for multisig scripts
|
||||
; "\x01" for Plutus V1 scripts
|
||||
; "\x02" for Plutus V2 scripts
|
||||
; "\x03" for Plutus V3 scripts
|
||||
scripthash = $hash28
|
||||
|
||||
datum_hash = $hash32
|
||||
data = #6.24(bytes .cbor plutus_data)
|
||||
|
||||
datum_option = [ 0, $hash32 // 1, data ]
|
||||
|
||||
script_ref = #6.24(bytes .cbor script)
|
||||
|
||||
script = [ 0, native_script // 1, plutus_v1_script // 2, plutus_v2_script // 3, plutus_v3_script ]
|
||||
3
pallas-primitives/src/conway/mod.rs
Normal file
3
pallas-primitives/src/conway/mod.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
mod model;
|
||||
|
||||
pub use model::*;
|
||||
1579
pallas-primitives/src/conway/model.rs
Normal file
1579
pallas-primitives/src/conway/model.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -5,5 +5,6 @@ mod framework;
|
|||
pub mod alonzo;
|
||||
pub mod babbage;
|
||||
pub mod byron;
|
||||
pub mod conway;
|
||||
|
||||
pub use framework::*;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::borrow::Cow;
|
|||
|
||||
use pallas_codec::minicbor;
|
||||
use pallas_crypto::hash::Hash;
|
||||
use pallas_primitives::{alonzo, babbage, byron};
|
||||
use pallas_primitives::{alonzo, babbage, byron, conway};
|
||||
|
||||
use crate::{probe, support, Era, Error, MultiEraBlock, MultiEraHeader, MultiEraTx};
|
||||
|
||||
|
|
@ -58,6 +58,13 @@ impl<'b> MultiEraBlock<'b> {
|
|||
Ok(Self::Babbage(Box::new(block)))
|
||||
}
|
||||
|
||||
pub fn decode_conway(cbor: &'b [u8]) -> Result<Self, Error> {
|
||||
let (_, block): BlockWrapper<conway::MintedBlock> =
|
||||
minicbor::decode(cbor).map_err(Error::invalid_cbor)?;
|
||||
|
||||
Ok(Self::Conway(Box::new(block)))
|
||||
}
|
||||
|
||||
pub fn decode(cbor: &'b [u8]) -> Result<MultiEraBlock<'b>, Error> {
|
||||
match probe::block_era(cbor) {
|
||||
probe::Outcome::EpochBoundary => Self::decode_epoch_boundary(cbor),
|
||||
|
|
@ -68,6 +75,7 @@ impl<'b> MultiEraBlock<'b> {
|
|||
Era::Mary => Self::decode_mary(cbor),
|
||||
Era::Alonzo => Self::decode_alonzo(cbor),
|
||||
Era::Babbage => Self::decode_babbage(cbor),
|
||||
Era::Conway => Self::decode_conway(cbor),
|
||||
},
|
||||
probe::Outcome::Inconclusive => Err(Error::unknown_cbor(cbor)),
|
||||
}
|
||||
|
|
@ -83,6 +91,7 @@ impl<'b> MultiEraBlock<'b> {
|
|||
MultiEraHeader::AlonzoCompatible(Cow::Borrowed(&x.header))
|
||||
}
|
||||
MultiEraBlock::Babbage(x) => MultiEraHeader::Babbage(Cow::Borrowed(&x.header)),
|
||||
MultiEraBlock::Conway(x) => MultiEraHeader::Babbage(Cow::Borrowed(&x.header)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -97,6 +106,7 @@ impl<'b> MultiEraBlock<'b> {
|
|||
MultiEraBlock::AlonzoCompatible(_, x) => *x,
|
||||
MultiEraBlock::Babbage(_) => Era::Babbage,
|
||||
MultiEraBlock::Byron(_) => Era::Byron,
|
||||
MultiEraBlock::Conway(_) => Era::Conway,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -123,6 +133,10 @@ impl<'b> MultiEraBlock<'b> {
|
|||
.into_iter()
|
||||
.map(|x| MultiEraTx::Byron(Box::new(Cow::Owned(x))))
|
||||
.collect(),
|
||||
MultiEraBlock::Conway(x) => support::clone_conway_txs(x)
|
||||
.into_iter()
|
||||
.map(|x| MultiEraTx::Conway(Box::new(Cow::Owned(x))))
|
||||
.collect(),
|
||||
MultiEraBlock::EpochBoundary(_) => vec![],
|
||||
}
|
||||
}
|
||||
|
|
@ -134,6 +148,7 @@ impl<'b> MultiEraBlock<'b> {
|
|||
MultiEraBlock::AlonzoCompatible(x, _) => x.transaction_bodies.is_empty(),
|
||||
MultiEraBlock::Babbage(x) => x.transaction_bodies.is_empty(),
|
||||
MultiEraBlock::Byron(x) => x.body.tx_payload.is_empty(),
|
||||
MultiEraBlock::Conway(x) => x.transaction_bodies.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -144,6 +159,7 @@ impl<'b> MultiEraBlock<'b> {
|
|||
MultiEraBlock::AlonzoCompatible(x, _) => x.transaction_bodies.len(),
|
||||
MultiEraBlock::Babbage(x) => x.transaction_bodies.len(),
|
||||
MultiEraBlock::Byron(x) => x.body.tx_payload.len(),
|
||||
MultiEraBlock::Conway(x) => x.transaction_bodies.len(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -154,33 +170,46 @@ impl<'b> MultiEraBlock<'b> {
|
|||
MultiEraBlock::AlonzoCompatible(x, _) => !x.auxiliary_data_set.is_empty(),
|
||||
MultiEraBlock::Babbage(x) => !x.auxiliary_data_set.is_empty(),
|
||||
MultiEraBlock::Byron(_) => false,
|
||||
MultiEraBlock::Conway(x) => !x.auxiliary_data_set.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_alonzo(&self) -> Option<&alonzo::MintedBlock> {
|
||||
match self {
|
||||
MultiEraBlock::EpochBoundary(_) => None,
|
||||
MultiEraBlock::AlonzoCompatible(x, _) => Some(x),
|
||||
MultiEraBlock::Babbage(_) => None,
|
||||
MultiEraBlock::Byron(_) => None,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_babbage(&self) -> Option<&babbage::MintedBlock> {
|
||||
match self {
|
||||
MultiEraBlock::EpochBoundary(_) => None,
|
||||
MultiEraBlock::AlonzoCompatible(_, _) => None,
|
||||
MultiEraBlock::Babbage(x) => Some(x),
|
||||
MultiEraBlock::Byron(_) => None,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_byron(&self) -> Option<&byron::MintedBlock> {
|
||||
match self {
|
||||
MultiEraBlock::EpochBoundary(_) => None,
|
||||
MultiEraBlock::AlonzoCompatible(_, _) => None,
|
||||
MultiEraBlock::Babbage(_) => None,
|
||||
MultiEraBlock::Byron(x) => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_conway(&self) -> Option<&conway::MintedBlock> {
|
||||
match self {
|
||||
MultiEraBlock::Conway(x) => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the size of the serialised block in bytes
|
||||
pub fn size(&self) -> usize {
|
||||
match self {
|
||||
MultiEraBlock::EpochBoundary(b) => minicbor::to_vec(b).unwrap().len(),
|
||||
MultiEraBlock::Byron(b) => minicbor::to_vec(b).unwrap().len(),
|
||||
MultiEraBlock::AlonzoCompatible(b, _) => minicbor::to_vec(b).unwrap().len(),
|
||||
MultiEraBlock::Babbage(b) => minicbor::to_vec(b).unwrap().len(),
|
||||
MultiEraBlock::Conway(b) => minicbor::to_vec(b).unwrap().len(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use pallas_primitives::alonzo;
|
||||
use pallas_primitives::{alonzo, conway};
|
||||
|
||||
use crate::MultiEraCert;
|
||||
|
||||
|
|
@ -9,4 +9,11 @@ impl<'b> MultiEraCert<'b> {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_conway(&self) -> Option<&conway::Certificate> {
|
||||
match self {
|
||||
MultiEraCert::Conway(x) => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ impl Era {
|
|||
Feature::CIP31 => self.ge(&Era::Babbage),
|
||||
Feature::CIP32 => self.ge(&Era::Babbage),
|
||||
Feature::CIP33 => self.ge(&Era::Babbage),
|
||||
Feature::CIP1694 => self.ge(&Era::Conway),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +32,7 @@ impl TryFrom<u16> for Era {
|
|||
4 => Ok(Era::Mary),
|
||||
5 => Ok(Era::Alonzo),
|
||||
6 => Ok(Era::Babbage),
|
||||
7 => Ok(Era::Conway),
|
||||
x => Err(crate::Error::UnknownEra(x)),
|
||||
}
|
||||
}
|
||||
|
|
@ -45,6 +47,7 @@ impl From<Era> for u16 {
|
|||
Era::Mary => 4,
|
||||
Era::Alonzo => 5,
|
||||
Era::Babbage => 6,
|
||||
Era::Conway => 7,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -58,6 +61,7 @@ impl Display for Era {
|
|||
Era::Mary => write!(f, "Mary"),
|
||||
Era::Alonzo => write!(f, "Alonzo"),
|
||||
Era::Babbage => write!(f, "Babbage"),
|
||||
Era::Conway => write!(f, "Conway"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{ComputeHash, OriginalHash};
|
||||
use pallas_codec::utils::KeepRaw;
|
||||
use pallas_crypto::hash::{Hash, Hasher};
|
||||
use pallas_primitives::{alonzo, babbage, byron};
|
||||
use pallas_primitives::{alonzo, babbage, byron, conway};
|
||||
|
||||
impl ComputeHash<32> for byron::EbbHead {
|
||||
fn compute_hash(&self) -> Hash<32> {
|
||||
|
|
@ -142,6 +142,32 @@ impl ComputeHash<32> for babbage::DatumOption {
|
|||
}
|
||||
}
|
||||
|
||||
// conway
|
||||
|
||||
impl ComputeHash<28> for conway::PlutusV3Script {
|
||||
fn compute_hash(&self) -> Hash<28> {
|
||||
Hasher::<224>::hash_tagged(&self.0, 3)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeHash<32> for conway::TransactionBody {
|
||||
fn compute_hash(&self) -> Hash<32> {
|
||||
Hasher::<256>::hash_cbor(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl OriginalHash<32> for KeepRaw<'_, conway::TransactionBody> {
|
||||
fn original_hash(&self) -> pallas_crypto::hash::Hash<32> {
|
||||
Hasher::<256>::hash(self.raw_cbor())
|
||||
}
|
||||
}
|
||||
|
||||
impl OriginalHash<32> for KeepRaw<'_, conway::MintedTransactionBody<'_>> {
|
||||
fn original_hash(&self) -> pallas_crypto::hash::Hash<32> {
|
||||
Hasher::<256>::hash(self.raw_cbor())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{Era, MultiEraTx};
|
||||
|
|
@ -318,7 +344,7 @@ mod tests {
|
|||
fn tx_wits_plutus_v1_script_hashes_as_cli() {
|
||||
let tx_bytecode_hex = include_str!("../../test_data/scriptwit.tx");
|
||||
let bytecode = hex::decode(tx_bytecode_hex).unwrap();
|
||||
let tx = MultiEraTx::decode(Era::Babbage, &bytecode).unwrap();
|
||||
let tx = MultiEraTx::decode_for_era(Era::Babbage, &bytecode).unwrap();
|
||||
|
||||
let generated = tx
|
||||
.plutus_v1_scripts()
|
||||
|
|
@ -346,7 +372,7 @@ mod tests {
|
|||
|
||||
let tx_hex = include_str!("../../test_data/babbage1.tx");
|
||||
let tx_bytes = hex::decode(tx_hex).unwrap();
|
||||
let tx = MultiEraTx::decode(Era::Babbage, &tx_bytes).unwrap();
|
||||
let tx = MultiEraTx::decode_for_era(Era::Babbage, &tx_bytes).unwrap();
|
||||
let data = tx.plutus_data();
|
||||
|
||||
for (datum, expected_hash) in data.iter().zip(expected) {
|
||||
|
|
@ -360,7 +386,7 @@ mod tests {
|
|||
|
||||
let tx_hex = include_str!("../../test_data/babbage2.tx");
|
||||
let tx_bytes = hex::decode(tx_hex).unwrap();
|
||||
let tx = MultiEraTx::decode(Era::Babbage, &tx_bytes).unwrap();
|
||||
let tx = MultiEraTx::decode_for_era(Era::Babbage, &tx_bytes).unwrap();
|
||||
|
||||
for output in tx.outputs() {
|
||||
if let Some(MintedDatumOption::Data(datum)) = output.datum() {
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ mod tests {
|
|||
fn test_duplicate_consumed_inputs() {
|
||||
let tx_bytecode_hex = include_str!("../../test_data/duplicateinput.tx");
|
||||
let bytecode = hex::decode(tx_bytecode_hex).unwrap();
|
||||
let tx = MultiEraTx::decode(Era::Alonzo, &bytecode).unwrap();
|
||||
let tx = MultiEraTx::decode_for_era(Era::Alonzo, &bytecode).unwrap();
|
||||
|
||||
let expected_inputs = vec![
|
||||
"4d9cb6bf1c2e349f1bcd454a632d2b721d5badcf687220430c316588f39506ab#1",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use thiserror::Error;
|
|||
|
||||
use pallas_codec::utils::{KeepRaw, KeyValuePairs};
|
||||
use pallas_crypto::hash::Hash;
|
||||
use pallas_primitives::{alonzo, babbage, byron};
|
||||
use pallas_primitives::{alonzo, babbage, byron, conway};
|
||||
|
||||
mod support;
|
||||
|
||||
|
|
@ -42,6 +42,7 @@ pub enum Era {
|
|||
Mary, // multi-assets
|
||||
Alonzo, // smart-contracts
|
||||
Babbage, // CIP-31/32/33
|
||||
Conway, // governance CIP-1694
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
|
|
@ -54,6 +55,7 @@ pub enum Feature {
|
|||
CIP31,
|
||||
CIP32,
|
||||
CIP33,
|
||||
CIP1694,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -71,6 +73,7 @@ pub enum MultiEraBlock<'b> {
|
|||
AlonzoCompatible(Box<alonzo::MintedBlock<'b>>, Era),
|
||||
Babbage(Box<babbage::MintedBlock<'b>>),
|
||||
Byron(Box<byron::MintedBlock<'b>>),
|
||||
Conway(Box<conway::MintedBlock<'b>>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
@ -79,6 +82,7 @@ pub enum MultiEraTx<'b> {
|
|||
AlonzoCompatible(Box<Cow<'b, alonzo::MintedTx<'b>>>, Era),
|
||||
Babbage(Box<Cow<'b, babbage::MintedTx<'b>>>),
|
||||
Byron(Box<Cow<'b, byron::MintedTxPayload<'b>>>),
|
||||
Conway(Box<Cow<'b, conway::MintedTx<'b>>>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
@ -101,6 +105,7 @@ pub enum MultiEraInput<'b> {
|
|||
pub enum MultiEraCert<'b> {
|
||||
NotApplicable,
|
||||
AlonzoCompatible(Box<Cow<'b, alonzo::Certificate>>),
|
||||
Conway(Box<Cow<'b, conway::Certificate>>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
|
|
@ -143,7 +148,6 @@ pub enum MultiEraWithdrawals<'b> {
|
|||
#[derive(Debug, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub enum MultiEraUpdate<'b> {
|
||||
NotApplicable,
|
||||
AlonzoCompatible(Box<Cow<'b, alonzo::Update>>),
|
||||
Babbage(Box<Cow<'b, babbage::Update>>),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ impl<'b> MultiEraOutput<'b> {
|
|||
let tx = Box::new(Cow::Owned(tx));
|
||||
Ok(Self::AlonzoCompatible(tx))
|
||||
}
|
||||
Era::Babbage => {
|
||||
Era::Babbage | Era::Conway => {
|
||||
let tx = minicbor::decode(cbor)?;
|
||||
let tx = Box::new(Cow::Owned(tx));
|
||||
Ok(Self::Babbage(tx))
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ pub fn block_era(cbor: &[u8]) -> Outcome {
|
|||
4 => Outcome::Matched(Era::Mary),
|
||||
5 => Outcome::Matched(Era::Alonzo),
|
||||
6 => Outcome::Matched(Era::Babbage),
|
||||
7 => Outcome::Matched(Era::Conway),
|
||||
_ => Outcome::Inconclusive,
|
||||
},
|
||||
_ => Outcome::Inconclusive,
|
||||
|
|
@ -99,4 +100,24 @@ mod tests {
|
|||
|
||||
assert!(matches!(inference, Outcome::Matched(Era::Alonzo)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn babbage_block_detected() {
|
||||
let block_str = include_str!("../../test_data/babbage1.block");
|
||||
let bytes = hex::decode(block_str).unwrap();
|
||||
|
||||
let inference = block_era(bytes.as_slice());
|
||||
|
||||
assert!(matches!(inference, Outcome::Matched(Era::Babbage)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn conway_block_detected() {
|
||||
let block_str = include_str!("../../test_data/conway1.artificial.block");
|
||||
let bytes = hex::decode(block_str).unwrap();
|
||||
|
||||
let inference = block_era(bytes.as_slice());
|
||||
|
||||
assert!(matches!(inference, Outcome::Matched(Era::Conway)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ impl<'b> MultiEraTx<'b> {
|
|||
_ => 2,
|
||||
},
|
||||
MultiEraTx::Byron(_) => 0,
|
||||
MultiEraTx::Conway(x) => match &x.auxiliary_data {
|
||||
Nullable::Some(x) => x.raw_cbor().len(),
|
||||
_ => 2,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -22,6 +26,7 @@ impl<'b> MultiEraTx<'b> {
|
|||
MultiEraTx::AlonzoCompatible(x, _) => x.transaction_body.raw_cbor().len(),
|
||||
MultiEraTx::Babbage(x) => x.transaction_body.raw_cbor().len(),
|
||||
MultiEraTx::Byron(x) => x.transaction.raw_cbor().len(),
|
||||
MultiEraTx::Conway(x) => x.transaction_body.raw_cbor().len(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -30,6 +35,7 @@ impl<'b> MultiEraTx<'b> {
|
|||
MultiEraTx::AlonzoCompatible(x, _) => x.transaction_witness_set.raw_cbor().len(),
|
||||
MultiEraTx::Babbage(x) => x.transaction_witness_set.raw_cbor().len(),
|
||||
MultiEraTx::Byron(x) => x.witness.raw_cbor().len(),
|
||||
MultiEraTx::Conway(x) => x.transaction_witness_set.raw_cbor().len(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -47,6 +53,7 @@ impl<'b> MultiEraBlock<'b> {
|
|||
MultiEraBlock::Babbage(x) => Some(x.header.header_body.block_body_size as usize),
|
||||
MultiEraBlock::EpochBoundary(_) => None,
|
||||
MultiEraBlock::Byron(_) => None,
|
||||
MultiEraBlock::Conway(x) => Some(x.header.header_body.block_body_size as usize),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//! Internal supporting utilities
|
||||
|
||||
use pallas_primitives::{alonzo, babbage, byron};
|
||||
use pallas_primitives::{alonzo, babbage, byron, conway};
|
||||
|
||||
macro_rules! clone_tx_fn {
|
||||
($fn_name:ident, $era:tt) => {
|
||||
|
|
@ -40,6 +40,7 @@ macro_rules! clone_tx_fn {
|
|||
};
|
||||
}
|
||||
|
||||
clone_tx_fn!(conway_clone_tx_at, conway);
|
||||
clone_tx_fn!(babbage_clone_tx_at, babbage);
|
||||
clone_tx_fn!(alonzo_clone_tx_at, alonzo);
|
||||
|
||||
|
|
@ -57,6 +58,13 @@ pub fn clone_babbage_txs<'b>(block: &'b babbage::MintedBlock) -> Vec<babbage::Mi
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub fn clone_conway_txs<'b>(block: &'b conway::MintedBlock) -> Vec<conway::MintedTx<'b>> {
|
||||
(0..block.transaction_bodies.len())
|
||||
.step_by(1)
|
||||
.filter_map(|idx| conway_clone_tx_at(block, idx))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn clone_byron_txs<'b>(block: &'b byron::MintedBlock) -> Vec<byron::MintedTxPayload<'b>> {
|
||||
block.body.tx_payload.iter().cloned().collect()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,6 +131,9 @@ impl<'a> MultiEraBlock<'a> {
|
|||
MultiEraBlock::Babbage(x) => {
|
||||
genesis.absolute_slot_to_relative(x.header.header_body.slot)
|
||||
}
|
||||
MultiEraBlock::Conway(x) => {
|
||||
genesis.absolute_slot_to_relative(x.header.header_body.slot)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ use pallas_crypto::hash::Hash;
|
|||
use pallas_primitives::{
|
||||
alonzo,
|
||||
babbage::{self, NetworkId},
|
||||
byron,
|
||||
byron, conway,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
Era, MultiEraCert, MultiEraInput, MultiEraMeta, MultiEraOutput, MultiEraPolicyAssets,
|
||||
MultiEraSigners, MultiEraTx, MultiEraUpdate, MultiEraWithdrawals, OriginalHash,
|
||||
MultiEraSigners, MultiEraTx, MultiEraUpdate, MultiEraWithdrawals, OriginalHash, Error
|
||||
};
|
||||
|
||||
impl<'b> MultiEraTx<'b> {
|
||||
|
|
@ -32,10 +32,11 @@ impl<'b> MultiEraTx<'b> {
|
|||
MultiEraTx::AlonzoCompatible(x, _) => minicbor::to_vec(x).unwrap(),
|
||||
MultiEraTx::Babbage(x) => minicbor::to_vec(x).unwrap(),
|
||||
MultiEraTx::Byron(x) => minicbor::to_vec(x).unwrap(),
|
||||
MultiEraTx::Conway(x) => minicbor::to_vec(x).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode(era: Era, cbor: &'b [u8]) -> Result<Self, minicbor::decode::Error> {
|
||||
pub fn decode_for_era(era: Era, cbor: &'b [u8]) -> Result<Self, minicbor::decode::Error> {
|
||||
match era {
|
||||
Era::Byron => {
|
||||
let tx = minicbor::decode(cbor)?;
|
||||
|
|
@ -52,6 +53,35 @@ impl<'b> MultiEraTx<'b> {
|
|||
let tx = Box::new(Cow::Owned(tx));
|
||||
Ok(MultiEraTx::Babbage(tx))
|
||||
}
|
||||
Era::Conway => {
|
||||
let tx = minicbor::decode(cbor)?;
|
||||
let tx = Box::new(Cow::Owned(tx));
|
||||
Ok(MultiEraTx::Conway(tx))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Try decode a transaction via every era's encoding format, starting with
|
||||
/// the most recent and returning on first success, or None if none are
|
||||
/// successful
|
||||
pub fn decode(cbor: &'b [u8]) -> Result<Self, Error> {
|
||||
if let Ok(tx) = minicbor::decode(cbor) {
|
||||
return Ok(MultiEraTx::Conway(Box::new(Cow::Owned(tx))))
|
||||
}
|
||||
|
||||
if let Ok(tx) = minicbor::decode(cbor) {
|
||||
return Ok(MultiEraTx::Babbage(Box::new(Cow::Owned(tx))))
|
||||
}
|
||||
|
||||
if let Ok(tx) = minicbor::decode(cbor) {
|
||||
// Shelley/Allegra/Mary/Alonzo will all decode to Alonzo
|
||||
return Ok(MultiEraTx::AlonzoCompatible(Box::new(Cow::Owned(tx)), Era::Alonzo))
|
||||
}
|
||||
|
||||
if let Ok(tx) = minicbor::decode(cbor) {
|
||||
Ok(MultiEraTx::Byron(Box::new(Cow::Owned(tx))))
|
||||
} else {
|
||||
Err(Error::unknown_cbor(cbor))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -60,6 +90,7 @@ impl<'b> MultiEraTx<'b> {
|
|||
MultiEraTx::AlonzoCompatible(_, era) => *era,
|
||||
MultiEraTx::Babbage(_) => Era::Babbage,
|
||||
MultiEraTx::Byron(_) => Era::Byron,
|
||||
MultiEraTx::Conway(_) => Era::Conway,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -68,6 +99,7 @@ impl<'b> MultiEraTx<'b> {
|
|||
MultiEraTx::AlonzoCompatible(x, _) => x.transaction_body.original_hash(),
|
||||
MultiEraTx::Babbage(x) => x.transaction_body.original_hash(),
|
||||
MultiEraTx::Byron(x) => x.transaction.original_hash(),
|
||||
MultiEraTx::Conway(x) => x.transaction_body.original_hash(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -91,6 +123,12 @@ impl<'b> MultiEraTx<'b> {
|
|||
.iter()
|
||||
.map(MultiEraOutput::from_byron)
|
||||
.collect(),
|
||||
MultiEraTx::Conway(x) => x
|
||||
.transaction_body
|
||||
.outputs
|
||||
.iter()
|
||||
.map(MultiEraOutput::from_babbage)
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -111,13 +149,17 @@ impl<'b> MultiEraTx<'b> {
|
|||
.outputs
|
||||
.get(index)
|
||||
.map(MultiEraOutput::from_byron),
|
||||
MultiEraTx::Conway(x) => x
|
||||
.transaction_body
|
||||
.outputs
|
||||
.get(index)
|
||||
.map(MultiEraOutput::from_babbage),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the transaction inputs
|
||||
///
|
||||
/// NOTE: It is possible for this to return duplicates. See
|
||||
/// https://github.com/input-output-hk/cardano-ledger/commit/a342b74f5db3d3a75eae3e2abe358a169701b1e7
|
||||
/// NOTE: It is possible for this to return duplicates before some point in the chain history. See https://github.com/input-output-hk/cardano-ledger/commit/a342b74f5db3d3a75eae3e2abe358a169701b1e7
|
||||
pub fn inputs(&self) -> Vec<MultiEraInput> {
|
||||
match self {
|
||||
MultiEraTx::AlonzoCompatible(x, _) => x
|
||||
|
|
@ -138,6 +180,12 @@ impl<'b> MultiEraTx<'b> {
|
|||
.iter()
|
||||
.map(MultiEraInput::from_byron)
|
||||
.collect(),
|
||||
MultiEraTx::Conway(x) => x
|
||||
.transaction_body
|
||||
.inputs
|
||||
.iter()
|
||||
.map(MultiEraInput::from_alonzo_compatible)
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -179,6 +227,13 @@ impl<'b> MultiEraTx<'b> {
|
|||
.map(|c| MultiEraCert::AlonzoCompatible(Box::new(Cow::Borrowed(c))))
|
||||
.collect(),
|
||||
MultiEraTx::Byron(_) => vec![],
|
||||
MultiEraTx::Conway(x) => x
|
||||
.transaction_body
|
||||
.certificates
|
||||
.iter()
|
||||
.flat_map(|c| c.iter())
|
||||
.map(|c| MultiEraCert::Conway(Box::new(Cow::Borrowed(c))))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -195,6 +250,7 @@ impl<'b> MultiEraTx<'b> {
|
|||
.as_ref()
|
||||
.map(MultiEraUpdate::from_babbage),
|
||||
MultiEraTx::Byron(_) => None,
|
||||
MultiEraTx::Conway(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -215,6 +271,14 @@ impl<'b> MultiEraTx<'b> {
|
|||
.map(|(k, v)| MultiEraPolicyAssets::AlonzoCompatibleMint(k, v))
|
||||
.collect(),
|
||||
MultiEraTx::Byron(_) => vec![],
|
||||
// TODO: Is this still AlonzoCompatible? Zero vals not allowed or something
|
||||
MultiEraTx::Conway(x) => x
|
||||
.transaction_body
|
||||
.mint
|
||||
.iter()
|
||||
.flat_map(|x| x.iter())
|
||||
.map(|(k, v)| MultiEraPolicyAssets::AlonzoCompatibleMint(k, v))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -239,6 +303,13 @@ impl<'b> MultiEraTx<'b> {
|
|||
.map(MultiEraInput::from_alonzo_compatible)
|
||||
.collect(),
|
||||
MultiEraTx::Byron(_) => vec![],
|
||||
MultiEraTx::Conway(x) => x
|
||||
.transaction_body
|
||||
.collateral
|
||||
.iter()
|
||||
.flat_map(|x| x.iter())
|
||||
.map(MultiEraInput::from_alonzo_compatible)
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -342,6 +413,11 @@ impl<'b> MultiEraTx<'b> {
|
|||
None => MultiEraWithdrawals::Empty,
|
||||
},
|
||||
MultiEraTx::Byron(_) => MultiEraWithdrawals::NotApplicable,
|
||||
// TODO: non empty still compatible?
|
||||
MultiEraTx::Conway(x) => match &x.transaction_body.withdrawals {
|
||||
Some(x) => MultiEraWithdrawals::AlonzoCompatible(x),
|
||||
None => MultiEraWithdrawals::Empty,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -350,6 +426,7 @@ impl<'b> MultiEraTx<'b> {
|
|||
MultiEraTx::AlonzoCompatible(x, _) => Some(x.transaction_body.fee),
|
||||
MultiEraTx::Babbage(x) => Some(x.transaction_body.fee),
|
||||
MultiEraTx::Byron(_) => None,
|
||||
MultiEraTx::Conway(x) => Some(x.transaction_body.fee),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -358,6 +435,7 @@ impl<'b> MultiEraTx<'b> {
|
|||
MultiEraTx::AlonzoCompatible(x, _) => x.transaction_body.ttl,
|
||||
MultiEraTx::Babbage(x) => x.transaction_body.ttl,
|
||||
MultiEraTx::Byron(_) => None,
|
||||
MultiEraTx::Conway(x) => x.transaction_body.ttl,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -372,6 +450,7 @@ impl<'b> MultiEraTx<'b> {
|
|||
MultiEraTx::AlonzoCompatible(x, _) => x.transaction_body.fee,
|
||||
MultiEraTx::Babbage(x) => x.transaction_body.fee,
|
||||
MultiEraTx::Byron(x) => crate::fees::compute_byron_fee(x, None),
|
||||
MultiEraTx::Conway(x) => x.transaction_body.fee,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -388,6 +467,11 @@ impl<'b> MultiEraTx<'b> {
|
|||
pallas_codec::utils::Nullable::Undefined => None,
|
||||
},
|
||||
MultiEraTx::Byron(_) => None,
|
||||
MultiEraTx::Conway(x) => match &x.auxiliary_data {
|
||||
pallas_codec::utils::Nullable::Some(x) => Some(x),
|
||||
pallas_codec::utils::Nullable::Null => None,
|
||||
pallas_codec::utils::Nullable::Undefined => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -423,6 +507,13 @@ impl<'b> MultiEraTx<'b> {
|
|||
.map(MultiEraSigners::AlonzoCompatible)
|
||||
.unwrap_or_default(),
|
||||
MultiEraTx::Byron(_) => MultiEraSigners::NotApplicable,
|
||||
// TODO: still compat?
|
||||
MultiEraTx::Conway(x) => x
|
||||
.transaction_body
|
||||
.required_signers
|
||||
.as_ref()
|
||||
.map(MultiEraSigners::AlonzoCompatible)
|
||||
.unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -431,6 +522,7 @@ impl<'b> MultiEraTx<'b> {
|
|||
MultiEraTx::AlonzoCompatible(x, _) => x.transaction_body.validity_interval_start,
|
||||
MultiEraTx::Babbage(x) => x.transaction_body.validity_interval_start,
|
||||
MultiEraTx::Byron(_) => None,
|
||||
MultiEraTx::Conway(x) => x.transaction_body.validity_interval_start,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -439,6 +531,7 @@ impl<'b> MultiEraTx<'b> {
|
|||
MultiEraTx::AlonzoCompatible(x, _) => x.transaction_body.network_id,
|
||||
MultiEraTx::Babbage(x) => x.transaction_body.network_id,
|
||||
MultiEraTx::Byron(_) => None,
|
||||
MultiEraTx::Conway(x) => x.transaction_body.network_id,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -447,30 +540,35 @@ impl<'b> MultiEraTx<'b> {
|
|||
MultiEraTx::AlonzoCompatible(x, _) => x.success,
|
||||
MultiEraTx::Babbage(x) => x.success,
|
||||
MultiEraTx::Byron(_) => true,
|
||||
MultiEraTx::Conway(x) => x.success,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_babbage(&self) -> Option<&babbage::MintedTx> {
|
||||
match self {
|
||||
MultiEraTx::AlonzoCompatible(_, _) => None,
|
||||
MultiEraTx::Babbage(x) => Some(x),
|
||||
MultiEraTx::Byron(_) => None,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_alonzo(&self) -> Option<&alonzo::MintedTx> {
|
||||
match self {
|
||||
MultiEraTx::AlonzoCompatible(x, _) => Some(x),
|
||||
MultiEraTx::Babbage(_) => None,
|
||||
MultiEraTx::Byron(_) => None,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_byron(&self) -> Option<&byron::MintedTxPayload> {
|
||||
match self {
|
||||
MultiEraTx::AlonzoCompatible(_, _) => None,
|
||||
MultiEraTx::Babbage(_) => None,
|
||||
MultiEraTx::Byron(x) => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_conway(&self) -> Option<&conway::MintedTx> {
|
||||
match self {
|
||||
MultiEraTx::Conway(x) => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
test_data/conway1.artificial.block
Normal file
1
test_data/conway1.artificial.block
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue