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

Remove gas price #3141

Closed
wants to merge 18 commits into from
Closed

Remove gas price #3141

wants to merge 18 commits into from

Conversation

gterzian
Copy link
Contributor

@gterzian gterzian commented Oct 10, 2022

FIX #3140

  • document all added functions
  • try in sandbox /simulation/labnet
  • unit tests on the added/changed features
    • make tests compile
    • make tests pass
  • add logs allowing easy debugging in case the changes caused problems
  • if the API has changed, update the API specification

@gterzian gterzian changed the title Remove gasp price Remove gas price Oct 10, 2022
@gterzian
Copy link
Contributor Author

@massalabs/core-team @damip Still have to fix a few tests that are failing(see those currently ignored), sorry I still cannot access discord...

@@ -546,7 +546,7 @@ impl Interface for InterfaceImpl {
validity_start: (u64, u8),
validity_end: (u64, u8),
max_gas: u64,
gas_price: u64,
_gas_price: u64,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@adrien-zinger I think removing this would change the public api for the running byte code correct? Is there a specific way to deal with such breaking changes?

Copy link
Member

Choose a reason for hiding this comment

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

@aoudiamoncef can you synchronize with @gterzian on that ? (through github)

@aoudiamoncef aoudiamoncef added api Issues related to the API breaking labels Oct 17, 2022
@@ -16,33 +16,32 @@
//!
//! ```json
//! {
//! "sender": "xxxx", // address that sent the message and spent max_gas*gas_price+coins on emission
//! "sender": "xxxx", // address that sent the message and spent max_gas+coins on emission
Copy link
Member

Choose a reason for hiding this comment

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

max_gas is not an amount of coins, but a quantity of gas.

=> address that sent the message and spent fee+coins on emission

//! "slot": {"period": 123455, "thread": 11}, // slot at which the message was emitted
//! "emission_index": 212, // index of the message emitted in this slot
//! "destination": "xxxx", // target address
//! "handler": "handle_message", // name of the handler function to call in the target SC
//! "validity_start": {"period": 123456, "thread": 12}, // the message can be handled starting from the validity_start slot (included)
//! "validity_end": {"period": 123457, "thread": 16}, // the message can be handled until the validity_end slot (excluded)
//! "max_gas": 12334, // max gas available when the handler is called
//! "gas_price": "124.23", // gas price for the handler call
Copy link
Member

Choose a reason for hiding this comment

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

this needs to be replaced by a fee: Amount property

//! "coins": "1111.11", // amount of coins to transfer to the destination address when calling its handler
//! "data": { ... any object ... } // data payload of the message, passed as the sole parameter of the destination handler when called
//! }
//! ```
//!
//! ## How to send a message during bytecode execution
//!
//! * messages are sent using an ABI: `send_message(target_address, target_handler, validity_start, validity_end, max_gas, gas_price, coins, data: JSON string) -> Result<(), ABIReturnError>`. Note that data has a configuration defined `max_async_message_data_size`.
//! * messages are sent using an ABI: `send_message(target_address, target_handler, validity_start, validity_end, max_gas, coins, data: JSON string) -> Result<(), ABIReturnError>`. Note that data has a configuration defined `max_async_message_data_size`.
Copy link
Member

Choose a reason for hiding this comment

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

gas_price needs to be replaced by a fee property

//! * when called, this ABI does this:
//! * it consumes `compute_gas_cost_of_message_storage(context.current_slot, validity_end_slot)` of gas in the current execution. This allows making the message emission more gas-consuming when it requires storing the message in queue for longer
//! * it consumes `max_gas * gas_price + coins` coins from the sender
//! * it consumes `max_gas + coins` coins from the sender
Copy link
Member

Choose a reason for hiding this comment

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

it consumes fee + coins

//! * it generates an `AsyncMessage` and stores it in an asynchronous pool
//!
//! Note that `max_gas*gas_price` coins are burned when sending the message.
//! Note that `max_gas` coins are burned when sending the message.
Copy link
Member

Choose a reason for hiding this comment

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

Gas and coins are fundamentally different resources.

fee coins are burned when sending the message

//!
//! ## How is the `AsyncPool` handled
//! ```md
//! * In the AsyncPool, Messages are kept sorted by `priority = AsyncMessageId(msg.max_gas * msg.gas_price, rev(msg.slot), rev(msg.emission_index))`
//! * In the AsyncPool, Messages are kept sorted by `priority = AsyncMessageId(msg.max_gas, rev(msg.slot), rev(msg.emission_index))`
Copy link
Member

@damip damip Oct 18, 2022

Choose a reason for hiding this comment

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

The main sorting criterion should be message.fee.

Sort by decreasing:

AsyncMessageId = (std::cmp::Reverse<Amount>, Slot, u64);

@@ -55,7 +54,6 @@
//! * credit target_address with M.coins
//! * run the target handler function with M.payload as parameter and the context:
//! * max_gas = M.max_gas
//! * gas_price = M.gas_price
Copy link
Member

Choose a reason for hiding this comment

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

fee = M.fee

Comment on lines +26 to +27
/// `(rev(max_gas), emission_slot, emission_index)`
pub type AsyncMessageId = (std::cmp::Reverse<u64>, Slot, u64);
Copy link
Member

@damip damip Oct 18, 2022

Choose a reason for hiding this comment

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

let's change it according to the comment above


pub struct AsyncMessageIdSerializer {
amount_serializer: AmountSerializer,
Copy link
Member

@damip damip Oct 18, 2022

Choose a reason for hiding this comment

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

there should be an AmountSerializer for the fee

slot_serializer: SlotSerializer,
u64_serializer: U64VarIntSerializer,
}

impl AsyncMessageIdSerializer {
pub fn new() -> Self {
Self {
amount_serializer: AmountSerializer::new(),
max_gas_serializer: U64VarIntSerializer::new(),
slot_serializer: SlotSerializer::new(),
u64_serializer: U64VarIntSerializer::new(),
Copy link
Member

Choose a reason for hiding this comment

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

let's rename this one emission_index_serializer

match gas_price
.checked_mul_u64(max_gas)
.and_then(|x| x.checked_add(fee))
match Amount::from_str(&max_gas.to_string())
Copy link
Member

@damip damip Oct 18, 2022

Choose a reason for hiding this comment

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

Gas is not an amount of coins. This check should be done on fee property only

match gas_price
.checked_mul_u64(max_gas)
.and_then(|x| x.checked_add(fee))
match Amount::from_str(&max_gas.to_string())
Copy link
Member

Choose a reason for hiding this comment

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

here as well, just use coins.checked_add(fee)

@@ -231,7 +231,7 @@ impl ExecutionState {
// get operation ID
let operation_id = operation.id;

// compute fee from (op.max_gas * op.gas_price + op.fee)
// compute fee from (op.max_gas + op.fee)
Copy link
Member

@damip damip Oct 18, 2022

Choose a reason for hiding this comment

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

total fee should just be op.fee and nothing else

@@ -571,7 +571,6 @@ impl Interface for InterfaceImpl {
validity_start: Slot::new(validity_start.0, validity_start.1),
validity_end: Slot::new(validity_end.0, validity_end.1),
max_gas,
gas_price: Amount::from_raw(gas_price),
Copy link
Member

Choose a reason for hiding this comment

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

  • this should be replaced by fee: Amount
  • massa-sc-runtime should also be updated

@@ -74,7 +74,6 @@ impl Serializer<StateChanges> for StateChangesSerializer {
/// destination: Address::from_str("A12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G").unwrap(),
/// handler: String::from("test"),
/// max_gas: 10000000,
/// gas_price: Amount::from_str("1").unwrap(),
Copy link
Member

Choose a reason for hiding this comment

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

fee

@@ -168,7 +167,6 @@ impl Deserializer<StateChanges> for StateChangesDeserializer {
/// destination: Address::from_str("A12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G").unwrap(),
/// handler: String::from("test"),
/// max_gas: 10000000,
/// gas_price: Amount::from_str("1").unwrap(),
Copy link
Member

Choose a reason for hiding this comment

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

fee

self.get_gas_price()
.saturating_mul_u64(self.get_gas_usage())
}

/// Get the total fee paid by the creator
pub fn get_total_fee(&self) -> Amount {
Copy link
Member

Choose a reason for hiding this comment

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

this function is now useless. use op.fee directly

} => gas_price
.saturating_mul_u64(*max_gas)
OperationType::ExecuteSC { max_gas, .. } => {
Amount::from_str(&max_gas.to_string()).unwrap_or(Amount::default())
Copy link
Member

Choose a reason for hiding this comment

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

here we should return just the coins property of executesc

also, going through strings is inefficient

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It seems OperationType::ExecuteSC does not have coins, would returning zero be appropriate?

Copy link
Member

Choose a reason for hiding this comment

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

true, let's return Amount::zero() like in the case of RollSell

Copy link
Member

Choose a reason for hiding this comment

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

continuing over at #3173

so this PR is abandoned and you continue on 3173 ?

OperationType::ExecuteSC { max_gas, .. } => {
Amount::from_str(&max_gas.to_string()).unwrap_or(Amount::default())
}
OperationType::CallSC { max_gas, coins, .. } => Amount::from_str(&max_gas.to_string())
Copy link
Member

Choose a reason for hiding this comment

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

here we should return just the coins property of CallSC

also, going through strings is inefficient

Copy link
Member

@damip damip left a comment

Choose a reason for hiding this comment

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

There are a few misunderstandings that can be cleared by adding some documentation maybe:

  • Only the fee parameter represents coins spent as fees, only the max_gas parameter represents the amount of gas (computing power) expected to be spent during the execution, and only the size of the operation represents the amount of block space used by the operation
  • Coins, gas and block space are three different dimensions (see https://en.wikipedia.org/wiki/Dimensional_analysis )
  • The Amount structure encodes Coins and nothing else (already documented for the Amount structure)
  • gas is encoded as u64
  • block space is encoded as u64
  • quotes from https://en.wikipedia.org/wiki/Dimensional_analysis#Dimensional_homogeneity :
    • One may take ratios of quantities with different dimensions, and multiply or divide them. However, only quantities having the same dimension may be compared, equated, added, or subtracted.
      • this means that max_gas + fee is illegal but max_gas / fee is legal

I've added the checklist to perform in order to consider this PR ready.
Let's make sure the PR is ready and reviewed by the end of the week.

@gterzian
Copy link
Contributor Author

gterzian commented Oct 19, 2022

@damip Thanks for the clarification! So the fee in all cases would come from that found on the operation, except for the send_message ABI where we'd have to add it as a call parameter?

@damip
Copy link
Member

damip commented Oct 19, 2022

@damip Thanks for the clarification! So the fee in all cases would come from that found on the operation, except for the send_message ABI where we'd have to add it as a call parameter?

Yes exactly

@damip
Copy link
Member

damip commented Oct 19, 2022

@gterzian I made a mistake in one of my comments above: the first criterion of the async pool sorting should not be msg.fee but rev(Ratio(msg.fee, max(msg.max_gas,1)))

@gterzian
Copy link
Contributor Author

continuing over at #3173

Amount::from_str(&max_gas.to_string()).unwrap_or(Amount::default())
}
OperationType::CallSC { max_gas, coins, .. } => Amount::from_str(&max_gas.to_string())
.unwrap_or(Amount::default())
Copy link
Member

Choose a reason for hiding this comment

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

clippy warn

} => gas_price
.saturating_mul_u64(*max_gas)
OperationType::ExecuteSC { max_gas, .. } => {
Amount::from_str(&max_gas.to_string()).unwrap_or(Amount::default())
Copy link
Member

Choose a reason for hiding this comment

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

clippy warn

/// Get the total fee paid by the creator
pub fn get_total_fee(&self) -> Amount {
self.get_gas_coins().saturating_add(self.content.fee)
self.content.fee.saturating_add(
Amount::from_str(&self.get_gas_usage().to_string()).unwrap_or(Amount::default()),
Copy link
Member

Choose a reason for hiding this comment

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

there is a design problem here as well (see other remarks)

@gterzian
Copy link
Contributor Author

Closing in favor of #3173

@gterzian gterzian closed this Oct 31, 2022
@AurelienFT AurelienFT deleted the remove_gas_price branch May 29, 2023 08:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api Issues related to the API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove gas_price
3 participants