lib.rs 54 KiB
Newer Older
	// This is exposed by BridgeHubRococo
	impl bp_bridge_hub_westend::ToBridgeHubWestendOutboundLaneApi<Block> for Runtime {
		fn message_details(
			lane: bp_messages::LaneId,
			begin: bp_messages::MessageNonce,
			end: bp_messages::MessageNonce,
		) -> Vec<bp_messages::OutboundMessageDetails> {
			bridge_runtime_common::messages_api::outbound_message_details::<
				Runtime,
				bridge_to_westend_config::WithBridgeHubWestendMessagesInstance,
	impl bp_polkadot_bulletin::PolkadotBulletinFinalityApi<Block> for Runtime {
		fn best_finalized() -> Option<bp_runtime::HeaderId<bp_polkadot_bulletin::Hash, bp_polkadot_bulletin::BlockNumber>> {
			BridgePolkadotBulletinGrandpa::best_finalized()
		}

		fn free_headers_interval() -> Option<bp_polkadot_bulletin::BlockNumber> {
			<Runtime as pallet_bridge_grandpa::Config<
				bridge_common_config::BridgeGrandpaRococoBulletinInstance
			>>::FreeHeadersInterval::get()
		}

		fn synced_headers_grandpa_info(
		) -> Vec<bp_header_chain::StoredHeaderGrandpaInfo<bp_polkadot_bulletin::Header>> {
			BridgePolkadotBulletinGrandpa::synced_headers_grandpa_info()
		}
	}

	impl bp_polkadot_bulletin::FromPolkadotBulletinInboundLaneApi<Block> for Runtime {
		fn message_details(
			lane: bp_messages::LaneId,
			messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>,
		) -> Vec<bp_messages::InboundMessageDetails> {
			bridge_runtime_common::messages_api::inbound_message_details::<
				Runtime,
				bridge_to_bulletin_config::WithRococoBulletinMessagesInstance,
			>(lane, messages)
		}
	}

	impl bp_polkadot_bulletin::ToPolkadotBulletinOutboundLaneApi<Block> for Runtime {
		fn message_details(
			lane: bp_messages::LaneId,
			begin: bp_messages::MessageNonce,
			end: bp_messages::MessageNonce,
		) -> Vec<bp_messages::OutboundMessageDetails> {
			bridge_runtime_common::messages_api::outbound_message_details::<
				Runtime,
				bridge_to_bulletin_config::WithRococoBulletinMessagesInstance,
			>(lane, begin, end)
		}
	}

	impl snowbridge_outbound_queue_runtime_api::OutboundQueueApi<Block, Balance> for Runtime {
		fn prove_message(leaf_index: u64) -> Option<snowbridge_pallet_outbound_queue::MerkleProof> {
			snowbridge_pallet_outbound_queue::api::prove_message::<Runtime>(leaf_index)
		fn calculate_fee(command: Command, parameters: Option<PricingParameters<Balance>>) -> Fee<Balance> {
			snowbridge_pallet_outbound_queue::api::calculate_fee::<Runtime>(command, parameters)
		}
	}

	impl snowbridge_system_runtime_api::ControlApi<Block> for Runtime {
Francisco Aguirre's avatar
Francisco Aguirre committed
		fn agent_id(location: VersionedLocation) -> Option<AgentId> {
			snowbridge_pallet_system::api::agent_id::<Runtime>(location)
	#[cfg(feature = "try-runtime")]
	impl frame_try_runtime::TryRuntime<Block> for Runtime {
		fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
			let weight = Executive::try_runtime_upgrade(checks).unwrap();
		fn execute_block(
			block: Block,
			state_root_check: bool,
			signature_check: bool,
			select: frame_try_runtime::TryStateSelect,
		) -> Weight {
			// NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to
			// have a backtrace here.
			Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap()
		}
	}

	#[cfg(feature = "runtime-benchmarks")]
	impl frame_benchmarking::Benchmark<Block> for Runtime {
		fn benchmark_metadata(extra: bool) -> (
			Vec<frame_benchmarking::BenchmarkList>,
			Vec<frame_support::traits::StorageInfo>,
		) {
			use frame_benchmarking::{Benchmarking, BenchmarkList};
			use frame_support::traits::StorageInfoTrait;
			use frame_system_benchmarking::Pallet as SystemBench;
			use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
			use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
			// This is defined once again in dispatch_benchmark, because list_benchmarks!
			// and add_benchmarks! are macros exported by define_benchmarks! macros and those types
			// are referenced in that call.
			type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::<Runtime>;
			type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::<Runtime>;

			use pallet_bridge_relayers::benchmarking::Pallet as BridgeRelayersBench;
			// Change weight file names.
			type WestendFinality = BridgeWestendGrandpa;
			type WithinWestend = pallet_bridge_parachains::benchmarking::Pallet::<Runtime, bridge_common_config::BridgeParachainWestendInstance>;
			type RococoToWestend = pallet_bridge_messages::benchmarking::Pallet ::<Runtime, bridge_to_westend_config::WithBridgeHubWestendMessagesInstance>;
			type RococoToRococoBulletin = pallet_bridge_messages::benchmarking::Pallet ::<Runtime, bridge_to_bulletin_config::WithRococoBulletinMessagesInstance>;
			let mut list = Vec::<BenchmarkList>::new();
			list_benchmarks!(list, extra);

			let storage_info = AllPalletsWithSystem::storage_info();
Oliver Tale-Yazdi's avatar
Oliver Tale-Yazdi committed
			(list, storage_info)
		}

		fn dispatch_benchmark(
			config: frame_benchmarking::BenchmarkConfig
		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {
			use frame_benchmarking::{Benchmarking, BenchmarkBatch, BenchmarkError};
			use sp_storage::TrackedStorageKey;
			impl frame_system_benchmarking::Config for Runtime {
				fn setup_set_code_requirements(code: &sp_std::vec::Vec<u8>) -> Result<(), BenchmarkError> {
					ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32);
					Ok(())
				}

				fn verify_set_code() {
					System::assert_last_event(cumulus_pallet_parachain_system::Event::<Runtime>::ValidationFunctionStored.into());
				}
			}

			use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
			impl cumulus_pallet_session_benchmarking::Config for Runtime {}

			use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
			impl pallet_xcm::benchmarking::Config for Runtime {
				type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper<
					xcm_config::XcmConfig,
					ExistentialDepositAsset,
					xcm_config::PriceForParentDelivery,
				>;

Francisco Aguirre's avatar
Francisco Aguirre committed
				fn reachable_dest() -> Option<Location> {
Francisco Aguirre's avatar
Francisco Aguirre committed
				fn teleportable_asset_and_dest() -> Option<(Asset, Location)> {
					// Relay/native token can be teleported between BH and Relay.
					Some((
Francisco Aguirre's avatar
Francisco Aguirre committed
						Asset {
Francisco Aguirre's avatar
Francisco Aguirre committed
							id: AssetId(Parent.into())
Francisco Aguirre's avatar
Francisco Aguirre committed
				fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> {
Francisco Aguirre's avatar
Francisco Aguirre committed
				) -> Option<(Assets, u32, Location, Box<dyn FnOnce()>)> {
					// BH only supports teleports to system parachain.
					// Relay/native token can be teleported between BH and Relay.
					let native_location = Parent.into();
					let dest = Parent.into();
					pallet_xcm::benchmarking::helpers::native_teleport_as_asset_transfer::<Runtime>(
						native_location,
						dest
					)
				}

				fn get_asset() -> Asset {
					Asset {
						id: AssetId(Location::parent()),
						fun: Fungible(ExistentialDeposit::get()),
					}
				}
			use xcm::latest::prelude::*;
			parameter_types! {
Francisco Aguirre's avatar
Francisco Aguirre committed
				pub ExistentialDepositAsset: Option<Asset> = Some((
					TokenLocation::get(),
					ExistentialDeposit::get()
				).into());
			}

			impl pallet_xcm_benchmarks::Config for Runtime {
				type XcmConfig = xcm_config::XcmConfig;
				type AccountIdConverter = xcm_config::LocationToAccountId;
				type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper<
Francisco Aguirre's avatar
Francisco Aguirre committed
					ExistentialDepositAsset,
					xcm_config::PriceForParentDelivery,
				>;
Francisco Aguirre's avatar
Francisco Aguirre committed
				fn valid_destination() -> Result<Location, BenchmarkError> {
Francisco Aguirre's avatar
Francisco Aguirre committed
				fn worst_case_holding(_depositable_count: u32) -> Assets {
					// just concrete assets according to relay chain.
Francisco Aguirre's avatar
Francisco Aguirre committed
					let assets: Vec<Asset> = vec![
						Asset {
							id: AssetId(TokenLocation::get()),
							fun: Fungible(1_000_000 * UNITS),
						}
					];
					assets.into()
				}
			}

			parameter_types! {
Francisco Aguirre's avatar
Francisco Aguirre committed
				pub const TrustedTeleporter: Option<(Location, Asset)> = Some((
Francisco Aguirre's avatar
Francisco Aguirre committed
					Asset { fun: Fungible(UNITS), id: AssetId(TokenLocation::get()) },
Gavin Wood's avatar
Gavin Wood committed
				pub const CheckedAccount: Option<(AccountId, xcm_builder::MintLocation)> = None;
Francisco Aguirre's avatar
Francisco Aguirre committed
				pub const TrustedReserve: Option<(Location, Asset)> = None;
			}

			impl pallet_xcm_benchmarks::fungible::Config for Runtime {
				type TransactAsset = Balances;

				type CheckedAccount = CheckedAccount;
				type TrustedTeleporter = TrustedTeleporter;
				type TrustedReserve = TrustedReserve;
Francisco Aguirre's avatar
Francisco Aguirre committed
				fn get_asset() -> Asset {
					Asset {
						id: AssetId(TokenLocation::get()),
Oliver Tale-Yazdi's avatar
Oliver Tale-Yazdi committed
						fun: Fungible(UNITS),
					}
				}
			}

			impl pallet_xcm_benchmarks::generic::Config for Runtime {
				type TransactAsset = Balances;
				type RuntimeCall = RuntimeCall;

				fn worst_case_response() -> (u64, Response) {
					(0u64, Response::Version(Default::default()))
				}

Francisco Aguirre's avatar
Francisco Aguirre committed
				fn worst_case_asset_exchange() -> Result<(Assets, Assets), BenchmarkError> {
Gavin Wood's avatar
Gavin Wood committed
					Err(BenchmarkError::Skip)
				}

Francisco Aguirre's avatar
Francisco Aguirre committed
				fn universal_alias() -> Result<(Location, Junction), BenchmarkError> {
Gavin Wood's avatar
Gavin Wood committed
					Err(BenchmarkError::Skip)
				}

Francisco Aguirre's avatar
Francisco Aguirre committed
				fn transact_origin_and_runtime_call() -> Result<(Location, RuntimeCall), BenchmarkError> {
					Ok((TokenLocation::get(), frame_system::Call::remark_with_event { remark: vec![] }.into()))
Francisco Aguirre's avatar
Francisco Aguirre committed
				fn subscribe_origin() -> Result<Location, BenchmarkError> {
Francisco Aguirre's avatar
Francisco Aguirre committed
				fn claimable_asset() -> Result<(Location, Location, Assets), BenchmarkError> {
Francisco Aguirre's avatar
Francisco Aguirre committed
					let assets: Assets = (AssetId(TokenLocation::get()), 1_000 * UNITS).into();
					let ticket = Location { parents: 0, interior: Here };
					Ok((origin, ticket, assets))
				}
				fn fee_asset() -> Result<Asset, BenchmarkError> {
					Ok(Asset {
						id: AssetId(TokenLocation::get()),
						fun: Fungible(1_000_000 * UNITS),
					})
				}

Francisco Aguirre's avatar
Francisco Aguirre committed
				fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> {
Gavin Wood's avatar
Gavin Wood committed
					Err(BenchmarkError::Skip)
				}

				fn export_message_origin_and_destination(
Francisco Aguirre's avatar
Francisco Aguirre committed
				) -> Result<(Location, NetworkId, InteriorLocation), BenchmarkError> {
					// save XCM version for remote bridge hub
					let _ = PolkadotXcm::force_xcm_version(
						RuntimeOrigin::root(),
						Box::new(bridge_to_westend_config::BridgeHubWestendLocation::get()),
						XCM_VERSION,
					).map_err(|e| {
						log::error!(
							"Failed to dispatch `force_xcm_version({:?}, {:?}, {:?})`, error: {:?}",
							RuntimeOrigin::root(),
							bridge_to_westend_config::BridgeHubWestendLocation::get(),
							XCM_VERSION,
							e
						);
						BenchmarkError::Stop("XcmVersion was not stored!")
					})?;
					Ok(
						(
							bridge_to_westend_config::FromAssetHubRococoToAssetHubWestendRoute::get().location,
							NetworkId::Westend,
Francisco Aguirre's avatar
Francisco Aguirre committed
							[Parachain(bridge_to_westend_config::AssetHubWestendParaId::get().into())].into()
Francisco Aguirre's avatar
Francisco Aguirre committed
				fn alias_origin() -> Result<(Location, Location), BenchmarkError> {
					Err(BenchmarkError::Skip)
				}
			}

			type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::<Runtime>;
			type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::<Runtime>;

			type WestendFinality = BridgeWestendGrandpa;
			type WithinWestend = pallet_bridge_parachains::benchmarking::Pallet::<Runtime, bridge_common_config::BridgeParachainWestendInstance>;
			type RococoToWestend = pallet_bridge_messages::benchmarking::Pallet ::<Runtime, bridge_to_westend_config::WithBridgeHubWestendMessagesInstance>;
			type RococoToRococoBulletin = pallet_bridge_messages::benchmarking::Pallet ::<Runtime, bridge_to_bulletin_config::WithRococoBulletinMessagesInstance>;
			use bridge_runtime_common::messages_benchmarking::{
				prepare_message_delivery_proof_from_grandpa_chain,
				prepare_message_delivery_proof_from_parachain,
				prepare_message_proof_from_parachain,
				generate_xcm_builder_bridge_message_sample,
			};
			use pallet_bridge_messages::benchmarking::{
				Config as BridgeMessagesConfig,
				MessageDeliveryProofParams,
				MessageProofParams,
			};

			impl BridgeMessagesConfig<bridge_to_westend_config::WithBridgeHubWestendMessagesInstance> for Runtime {
				fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool {
					let bench_lane_id = <Self as BridgeMessagesConfig<bridge_to_westend_config::WithBridgeHubWestendMessagesInstance>>::bench_lane_id();
					let bridged_chain_id = bridge_to_westend_config::BridgeHubWestendChainId::get();
					pallet_bridge_relayers::Pallet::<Runtime>::relayer_reward(
						relayer,
						bp_relayers::RewardsAccountParams::new(
							bench_lane_id,
							bridged_chain_id,
							bp_relayers::RewardsAccountOwner::BridgedChain
						)
					).is_some()
				}

				fn prepare_message_proof(
					params: MessageProofParams,
				) -> (bridge_to_westend_config::FromWestendBridgeHubMessagesProof, Weight) {
					use cumulus_primitives_core::XcmpMessageSource;
					assert!(XcmpQueue::take_outbound_messages(usize::MAX).is_empty());
					ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(42.into());
					prepare_message_proof_from_parachain::<
						Runtime,
						bridge_common_config::BridgeGrandpaWestendInstance,
						bridge_to_westend_config::WithBridgeHubWestendMessageBridge,
Francisco Aguirre's avatar
Francisco Aguirre committed
					>(params, generate_xcm_builder_bridge_message_sample([GlobalConsensus(Rococo), Parachain(42)].into()))
				}

				fn prepare_message_delivery_proof(
					params: MessageDeliveryProofParams<AccountId>,
				) -> bridge_to_westend_config::ToWestendBridgeHubMessagesDeliveryProof {
					prepare_message_delivery_proof_from_parachain::<
						Runtime,
						bridge_common_config::BridgeGrandpaWestendInstance,
						bridge_to_westend_config::WithBridgeHubWestendMessageBridge,
					>(params)
				}

				fn is_message_successfully_dispatched(_nonce: bp_messages::MessageNonce) -> bool {
					use cumulus_primitives_core::XcmpMessageSource;
					!XcmpQueue::take_outbound_messages(usize::MAX).is_empty()
				}
			}

			impl BridgeMessagesConfig<bridge_to_bulletin_config::WithRococoBulletinMessagesInstance> for Runtime {
				fn is_relayer_rewarded(_relayer: &Self::AccountId) -> bool {
					// we do not pay any rewards in this bridge
					true
				}

				fn prepare_message_proof(
					params: MessageProofParams,
				) -> (bridge_to_bulletin_config::FromRococoBulletinMessagesProof, Weight) {
					use cumulus_primitives_core::XcmpMessageSource;
					assert!(XcmpQueue::take_outbound_messages(usize::MAX).is_empty());
					ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(42.into());
					prepare_message_proof_from_grandpa_chain::<
						Runtime,
						bridge_common_config::BridgeGrandpaRococoBulletinInstance,
						bridge_to_bulletin_config::WithRococoBulletinMessageBridge,
Francisco Aguirre's avatar
Francisco Aguirre committed
					>(params, generate_xcm_builder_bridge_message_sample([GlobalConsensus(Rococo), Parachain(42)].into()))
				}

				fn prepare_message_delivery_proof(
					params: MessageDeliveryProofParams<AccountId>,
				) -> bridge_to_bulletin_config::ToRococoBulletinMessagesDeliveryProof {
					prepare_message_delivery_proof_from_grandpa_chain::<
						Runtime,
						bridge_common_config::BridgeGrandpaRococoBulletinInstance,
						bridge_to_bulletin_config::WithRococoBulletinMessageBridge,
					>(params)
				}

				fn is_message_successfully_dispatched(_nonce: bp_messages::MessageNonce) -> bool {
					use cumulus_primitives_core::XcmpMessageSource;
					!XcmpQueue::take_outbound_messages(usize::MAX).is_empty()
				}
			}

			use bridge_runtime_common::parachains_benchmarking::prepare_parachain_heads_proof;
			use pallet_bridge_parachains::benchmarking::Config as BridgeParachainsConfig;
			use pallet_bridge_relayers::benchmarking::{
				Pallet as BridgeRelayersBench,
				Config as BridgeRelayersConfig,
			};

			impl BridgeParachainsConfig<bridge_common_config::BridgeParachainWestendInstance> for Runtime {
				fn parachains() -> Vec<bp_polkadot_core::parachains::ParaId> {
					use bp_runtime::Parachain;
					vec![bp_polkadot_core::parachains::ParaId(bp_bridge_hub_westend::BridgeHubWestend::PARACHAIN_ID)]
				}

				fn prepare_parachain_heads_proof(
					parachains: &[bp_polkadot_core::parachains::ParaId],
					parachain_head_size: u32,
					proof_size: bp_runtime::StorageProofSize,
				) -> (
					pallet_bridge_parachains::RelayBlockNumber,
					pallet_bridge_parachains::RelayBlockHash,
					bp_polkadot_core::parachains::ParaHeadsProof,
					Vec<(bp_polkadot_core::parachains::ParaId, bp_polkadot_core::parachains::ParaHash)>,
				) {
					prepare_parachain_heads_proof::<Runtime, bridge_common_config::BridgeParachainWestendInstance>(
						parachains,
						parachain_head_size,
						proof_size,
					)
				}
			}

			impl BridgeRelayersConfig for Runtime {
				fn prepare_rewards_account(
					account_params: bp_relayers::RewardsAccountParams,
					reward: Balance,
				) {
					let rewards_account = bp_relayers::PayRewardFromAccount::<
						Balances,
						AccountId
					>::rewards_account(account_params);
					Self::deposit_account(rewards_account, reward);
				}

				fn deposit_account(account: AccountId, balance: Balance) {
					use frame_support::traits::fungible::Mutate;
					Balances::mint_into(&account, balance.saturating_add(ExistentialDeposit::get())).unwrap();
				}
			}

			let whitelist: Vec<TrackedStorageKey> = vec![
				// Block Number
				hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),
				// Total Issuance
				hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),
				// Execution Phase
				hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),
				// Event Count
				hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),
				// System Events
				hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),
			];

			let mut batches = Vec::<BenchmarkBatch>::new();
			let params = (&config, &whitelist);
			add_benchmarks!(params, batches);

			Ok(batches)
		}
	}

	impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
		fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
			build_state::<RuntimeGenesisConfig>(config)
		fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
			get_preset::<RuntimeGenesisConfig>(id, |_| None)
		}

		fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
			vec![]
}

cumulus_pallet_parachain_system::register_validate_block! {
	Runtime = Runtime,
	BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
}

#[cfg(test)]
mod tests {
	use super::*;
	use codec::Encode;
	use sp_runtime::{
		generic::Era,

	#[test]
	fn ensure_signed_extension_definition_is_compatible_with_relay() {
		use bp_polkadot_core::SuffixedCommonSignedExtensionExt;

		sp_io::TestExternalities::default().execute_with(|| {
			frame_system::BlockHash::<Runtime>::insert(BlockNumber::zero(), Hash::default());
				frame_system::CheckNonZeroSender::new(),
				frame_system::CheckSpecVersion::new(),
				frame_system::CheckTxVersion::new(),
				frame_system::CheckGenesis::new(),
				frame_system::CheckEra::from(Era::Immortal),
				frame_system::CheckNonce::from(10),
				frame_system::CheckWeight::new(),
				pallet_transaction_payment::ChargeTransactionPayment::from(10),
				BridgeRejectObsoleteHeadersAndMessages,
				(
					bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages::default(),
					bridge_to_bulletin_config::OnBridgeHubRococoRefundRococoBulletinMessages::default(),
				),
				cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim::new(),
				let bhr_indirect_payload = bp_bridge_hub_rococo::SignedExtension::from_params(
					VERSION.spec_version,
					VERSION.transaction_version,
					bp_runtime::TransactionEra::Immortal,
					System::block_hash(BlockNumber::zero()),
					10,
					10,
					(((), ()), ((), ())),
				);
				assert_eq!(payload.encode(), bhr_indirect_payload.encode());
				assert_eq!(
					payload.additional_signed().unwrap().encode(),
					bhr_indirect_payload.additional_signed().unwrap().encode()