Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pruntime: Event chain #1304

Merged
merged 15 commits into from
Jul 10, 2023
Merged

pruntime: Event chain #1304

merged 15 commits into from
Jul 10, 2023

Conversation

kvinwang
Copy link
Collaborator

@kvinwang kvinwang commented Jun 14, 2023

Overview

This PR adds an events chain for external tools to track some public information about Clusters.
This is an alternative(maybe better) solution for #1287

The events chain blocks are emitted via logs so that pruntime can optionally turn it off.
Example log:

27633:2023-06-14T06:54:47.094931Z  INFO prpc{id=1453}:ecall:ocall: phactory::event_chain: number=46 payload=905e4367205d5a852c8bffdb6ad16fb435baab9dd56931d7a37cc8c6359100f92e000000000000009e00000001000000010000000c0202027d036356f407caf045728196c01e39a1af01c71846a1ca47fc73d561bb9f7842d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d0088526a740000000000000000000000000204067d036356f407caf045728196c01e39a1af01c71846a1ca47fc73d561bb9f78427d036356f407caf045728196c01e39a1af01c71846a1ca47fc73d561bb9f784208814a4097fefe74549e375f6c94b7407190922078a579f86ac9faa7af200ad4b1814a4097fefe74549e375f6c94b7407190922078a579f86ac9faa7af200ad4b1020202d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d7d036356f407caf045728196c01e39a1af01c71846a1ca47fc73d561bb9f7842d3620cea73000000000000000000000000
27646:2023-06-14T06:54:47.792065Z  INFO prpc{id=1453}:ecall:ocall: phactory::event_chain: number=47 payload=628df0c32ebf3f2349d1152e3ac66df980cb743231926bbe9e7658e33c0a71bd2f000000000000009f00000001000000010000000c0202027d036356f407caf045728196c01e39a1af01c71846a1ca47fc73d561bb9f7842d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d0088526a740000000000000000000000000204067d036356f407caf045728196c01e39a1af01c71846a1ca47fc73d561bb9f78427d036356f407caf045728196c01e39a1af01c71846a1ca47fc73d561bb9f784208814a4097fefe74549e375f6c94b7407190922078a579f86ac9faa7af200ad4b1814a4097fefe74549e375f6c94b7407190922078a579f86ac9faa7af200ad4b1020202d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d7d036356f407caf045728196c01e39a1af01c71846a1ca47fc73d561bb9f7842d3620cea73000000000000000000000000

we can write some script to collect them.

Drawback of #1287

There is a drawback in #1287 that there is always storage overhead to store the history records for each contract and the storage usage is not charged to any account.

We might still need the driver_history part in #1287 since it is low storage overhead and charged, so I extract it to a new PR #1305.

What information would be emitted?

All events from the System::events() except some private pink messages would be emitted.
Please check the list below to make sure no privacy info would be leaked:

        /// Events from System
        pub enum Event<T: Config> {
		/// An extrinsic completed successfully.
		ExtrinsicSuccess { dispatch_info: DispatchInfo },
		/// An extrinsic failed.
		ExtrinsicFailed { dispatch_error: DispatchError, dispatch_info: DispatchInfo },
		/// `:code` was updated.
		CodeUpdated,
		/// A new account was created.
		NewAccount { account: T::AccountId },
		/// An account was reaped.
		KilledAccount { account: T::AccountId },
		/// On on-chain remark happened.
		Remarked { sender: T::AccountId, hash: T::Hash },
	}
        /// Events from Balances
	pub enum Event<T: Config<I>, I: 'static = ()> {
		/// An account was created with some free balance.
		Endowed { account: T::AccountId, free_balance: T::Balance },
		/// An account was removed whose balance was non-zero but below ExistentialDeposit,
		/// resulting in an outright loss.
		DustLost { account: T::AccountId, amount: T::Balance },
		/// Transfer succeeded.
		Transfer { from: T::AccountId, to: T::AccountId, amount: T::Balance },
		/// A balance was set by root.
		BalanceSet { who: T::AccountId, free: T::Balance },
		/// Some balance was reserved (moved from free to reserved).
		Reserved { who: T::AccountId, amount: T::Balance },
		/// Some balance was unreserved (moved from reserved to free).
		Unreserved { who: T::AccountId, amount: T::Balance },
		/// Some balance was moved from the reserve of the first account to the second account.
		/// Final argument indicates the destination balance type.
		ReserveRepatriated {
			from: T::AccountId,
			to: T::AccountId,
			amount: T::Balance,
			destination_status: Status,
		},
		/// Some amount was deposited (e.g. for transaction fees).
		Deposit { who: T::AccountId, amount: T::Balance },
		/// Some amount was withdrawn from the account (e.g. for transaction fees).
		Withdraw { who: T::AccountId, amount: T::Balance },
		/// Some amount was removed from the account (e.g. for misbehavior).
		Slashed { who: T::AccountId, amount: T::Balance },
		/// Some amount was minted into an account.
		Minted { who: T::AccountId, amount: T::Balance },
		/// Some amount was burned from an account.
		Burned { who: T::AccountId, amount: T::Balance },
		/// Some amount was suspended from an account (it can be restored later).
		Suspended { who: T::AccountId, amount: T::Balance },
		/// Some amount was restored into an account.
		Restored { who: T::AccountId, amount: T::Balance },
		/// An account was upgraded.
		Upgraded { who: T::AccountId },
		/// Total issuance was increased by `amount`, creating a credit to be balanced.
		Issued { amount: T::Balance },
		/// Total issuance was decreased by `amount`, creating a debt to be balanced.
		Rescinded { amount: T::Balance },
		/// Some balance was locked.
		Locked { who: T::AccountId, amount: T::Balance },
		/// Some balance was unlocked.
		Unlocked { who: T::AccountId, amount: T::Balance },
		/// Some balance was frozen.
		Frozen { who: T::AccountId, amount: T::Balance },
		/// Some balance was thawed.
		Thawed { who: T::AccountId, amount: T::Balance },
	}
        /// Event from Contracts
	pub enum Event<T: Config> {
		/// Contract deployed by address at the specified address.
		Instantiated { deployer: T::AccountId, contract: T::AccountId },

		/// Contract has been removed.
		///
		/// # Note
		///
		/// The only way for a contract to be removed and emitting this event is by calling
		/// `seal_terminate`.
		Terminated {
			/// The contract that was terminated.
			contract: T::AccountId,
			/// The account that received the contracts remaining balance
			beneficiary: T::AccountId,
		},

		/// Code with the specified hash has been stored.
		CodeStored { code_hash: T::Hash },

		/// A custom event emitted by the contract.
		ContractEmitted {
			/// The contract that emitted the event.
			contract: T::AccountId,
			/// Data supplied by the contract. Metadata generated during contract compilation
			/// is needed to decode it.
			data: Vec<u8>,
		},

		/// A code with the specified hash was removed.
		CodeRemoved { code_hash: T::Hash },

		/// A contract's code was updated.
		ContractCodeUpdated {
			/// The contract that has been updated.
			contract: T::AccountId,
			/// New code hash that was set for the contract.
			new_code_hash: T::Hash,
			/// Previous code hash of the contract.
			old_code_hash: T::Hash,
		},

		/// A contract was called either by a plain account or another contract.
		///
		/// # Note
		///
		/// Please keep in mind that like all events this is only emitted for successful
		/// calls. This is because on failure all storage changes including events are
		/// rolled back.
		Called {
			/// The account that called the `contract`.
			caller: T::AccountId,
			/// The contract that was called.
			contract: T::AccountId,
		},

		/// A contract delegate called a code hash.
		///
		/// # Note
		///
		/// Please keep in mind that like all events this is only emitted for successful
		/// calls. This is because on failure all storage changes including events are
		/// rolled back.
		DelegateCalled {
			/// The contract that performed the delegate call and hence in whose context
			/// the `code_hash` is executed.
			contract: T::AccountId,
			/// The code hash that was delegate called.
			code_hash: CodeHash<T>,
		},
	}

For the ink event we extended to communicate to runtime, we filtered out the private ones:

    pub fn is_private(&self) -> bool {
        match self {
            PinkEvent::SetHook { .. } => false,
            PinkEvent::DeploySidevmTo { .. } => false,
            PinkEvent::SidevmMessage(_) => true,
            PinkEvent::CacheOp(_) => true,
            PinkEvent::StopSidevm => false,
            PinkEvent::ForceStopSidevm { .. } => false,
            PinkEvent::SetLogHandler(_) => false,
            PinkEvent::SetContractWeight { .. } => false,
            PinkEvent::UpgradeRuntimeTo { .. } => false,
        }
    }

@kvinwang kvinwang changed the title pruntime: Emit event chain pruntime: Event chain Jun 14, 2023
@h4x3rotab
Copy link
Contributor

Concept ACK. Will review the detailed code soon.

@kvinwang kvinwang mentioned this pull request Jun 30, 2023
2 tasks
Copy link
Contributor

@h4x3rotab h4x3rotab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice if we can also copy part of the PR description as a RFC in the repo for future reference.

crates/pink/pink-extension/src/system.rs Outdated Show resolved Hide resolved
}
Err(_) => {
error!("Contract emitted an invalid pink event");
}
}
} else {
ink_events.push((address, event.topics, data));
ink_events.push((address.clone(), event.topics.clone(), data.clone()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we know which tx the event belongs to based on the above information? If not, I suggest to add more data fields since it would be nice if we can group events emitted by a single call.

Copy link
Collaborator Author

@kvinwang kvinwang Jul 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Events are already grouped by single call because each call would emit a events block.
For contract call, we can further add the nonce to the corresponding events block, so that it can be connect to the original tx from the Phala chain.

Added.

crates/pink/runtime/src/runtime/pallet_pink.rs Outdated Show resolved Hide resolved
crates/pink/runtime/src/storage/mod.rs Show resolved Hide resolved
@kvinwang
Copy link
Collaborator Author

kvinwang commented Jul 5, 2023

Would be nice if we can also copy part of the PR description as a RFC in the repo for future reference.

Added docs/event-chain.md.

@kvinwang kvinwang requested a review from h4x3rotab July 6, 2023 11:29
@kvinwang
Copy link
Collaborator Author

kvinwang commented Jul 7, 2023

Also added entry contract to the block. @h4x3rotab

Copy link
Contributor

@h4x3rotab h4x3rotab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

docs/event-chain.md Outdated Show resolved Hide resolved
docs/event-chain.md Outdated Show resolved Hide resolved
@kvinwang kvinwang enabled auto-merge July 10, 2023 02:51
@kvinwang kvinwang merged commit f925692 into master Jul 10, 2023
8 checks passed
@kvinwang kvinwang deleted the event-chain branch July 10, 2023 04:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants