Skip to content

Commit faa2e94

Browse files
Merge pull request #169 from casper-network/release-2.0.4-patch-2
[BUG] Dynamic Gas Price Integration
2 parents ed0a507 + 1488b09 commit faa2e94

7 files changed

Lines changed: 193 additions & 99 deletions

File tree

node/src/components/contract_runtime/operations.rs

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,7 @@ pub fn execute_finalized_block(
485485
ProofHandling::NoProofs,
486486
));
487487

488+
artifact_builder.with_available(post_payment_balance_result.available_balance().copied());
488489
let lane_id = transaction.transaction_lane();
489490

490491
let allow_execution = {
@@ -494,21 +495,14 @@ pub fn execute_finalized_block(
494495
// amount in the happy path or the penalty amount in the sad path...in whichever case
495496
// the sad path is handled by is_penalty and the balance in the payment purse is
496497
// the penalty payment or the full amount but is 'sufficient' either way
497-
let cost = artifact_builder.cost_to_use();
498+
let actual_cost = artifact_builder.actual_cost(); // use actual cost here
498499
let is_sufficient_balance =
499-
is_custom_payment || post_payment_balance_result.is_sufficient(cost);
500+
is_custom_payment || post_payment_balance_result.is_sufficient(actual_cost);
500501
let is_allowed_by_chainspec = chainspec.is_supported(lane_id);
501502
let allow = is_not_penalized && is_sufficient_balance && is_allowed_by_chainspec;
502503
if !allow {
503504
let err_msg = {
504505
if !is_sufficient_balance {
505-
if let Some(available) = post_payment_balance_result.available_balance() {
506-
// they can't afford it so take available
507-
let available = *available;
508-
if available < cost {
509-
artifact_builder.with_cost(available);
510-
}
511-
}
512506
"Insufficient funds".to_string()
513507
} else {
514508
format!(
@@ -741,11 +735,13 @@ pub fn execute_finalized_block(
741735
let refund_amount = {
742736
let consumed =
743737
if balance_identifier.is_penalty() || artifact_builder.error_message().is_some() {
744-
artifact_builder.limit() // no refund for penalty
738+
artifact_builder.cost_to_use() // no refund for penalty
745739
} else {
746740
artifact_builder.consumed()
747741
};
748742

743+
let available = artifact_builder.available().unwrap_or(U512::zero());
744+
749745
let refund_mode = match refund_handling {
750746
RefundHandling::NoRefund => {
751747
if fee_handling.is_no_fee() && is_custom_payment {
@@ -771,6 +767,7 @@ pub fn execute_finalized_block(
771767
consumed,
772768
source: Box::new(balance_identifier.clone()),
773769
ratio: refund_ratio,
770+
available,
774771
}),
775772
RefundHandling::Refund { refund_ratio } => {
776773
let source = Box::new(balance_identifier.clone());
@@ -787,7 +784,6 @@ pub fn execute_finalized_block(
787784
// purposes of refund. instead, `BalanceIdentifier::Refund` is used by outer
788785
// logic, which is interpreted by inner logic to use the currently set
789786
// refund purse.
790-
let target = Box::new(BalanceIdentifier::Refund);
791787
Some(HandleRefundMode::Refund {
792788
initiator_addr: Box::new(initiator_addr.clone()),
793789
limit: artifact_builder.limit(),
@@ -796,7 +792,8 @@ pub fn execute_finalized_block(
796792
cost: artifact_builder.cost_to_use(),
797793
ratio: refund_ratio,
798794
source,
799-
target,
795+
target: Box::new(BalanceIdentifier::Refund),
796+
available,
800797
})
801798
} else {
802799
// in normal payment handling we put a temporary processing hold
@@ -808,15 +805,14 @@ pub fn execute_finalized_block(
808805
// the churn of taking the token up front via transfer (which writes
809806
// multiple permanent records) and then transfer some of it back (which
810807
// writes more permanent records).
811-
let calculated_refund_amount = HandleRefundMode::CalculateAmount {
808+
Some(HandleRefundMode::CalculateAmount {
812809
limit: artifact_builder.limit(),
813810
gas_price: current_gas_price,
814811
consumed,
815812
cost: artifact_builder.cost_to_use(),
816813
ratio: refund_ratio,
817-
source,
818-
};
819-
Some(calculated_refund_amount)
814+
available,
815+
})
820816
}
821817
}
822818
};
@@ -843,16 +839,22 @@ pub fn execute_finalized_block(
843839
}
844840
};
845841
artifact_builder.with_refund_amount(refund_amount);
842+
843+
// take the lower of the difference between cost - refund OR available
844+
let fee_amount = artifact_builder
845+
.cost_to_use()
846+
.saturating_sub(refund_amount)
847+
.min(artifact_builder.available().unwrap_or(U512::zero()));
848+
846849
// handle fees per the chainspec determined setting.
847850
let handle_fee_result = match fee_handling {
848851
FeeHandling::NoFee => {
849852
// in this mode, a gas hold is placed on the payer's purse.
850-
let amount = artifact_builder.cost_to_use().saturating_sub(refund_amount);
851853
let hold_request = BalanceHoldRequest::new_gas_hold(
852854
state_root_hash,
853855
protocol_version,
854856
balance_identifier,
855-
amount,
857+
fee_amount,
856858
insufficient_balance_handling,
857859
);
858860
let hold_result = scratch_state.balance_hold(hold_request);
@@ -866,25 +868,23 @@ pub fn execute_finalized_block(
866868
state_root_hash,
867869
protocol_version,
868870
transaction_hash,
869-
HandleFeeMode::credit(proposer.clone(), amount, era_id),
871+
HandleFeeMode::credit(proposer.clone(), fee_amount, era_id),
870872
);
871873
scratch_state.handle_fee(handle_fee_request)
872874
}
873875
FeeHandling::Burn => {
874876
// in this mode, the fee portion is burned.
875-
let amount = artifact_builder.cost_to_use().saturating_sub(refund_amount);
876877
let handle_fee_request = HandleFeeRequest::new(
877878
native_runtime_config.clone(),
878879
state_root_hash,
879880
protocol_version,
880881
transaction_hash,
881-
HandleFeeMode::burn(balance_identifier, Some(amount)),
882+
HandleFeeMode::burn(balance_identifier, Some(fee_amount)),
882883
);
883884
scratch_state.handle_fee(handle_fee_request)
884885
}
885886
FeeHandling::PayToProposer => {
886887
// in this mode, the consumed gas is paid as a fee to the block proposer
887-
let amount = artifact_builder.cost_to_use().saturating_sub(refund_amount);
888888
let handle_fee_request = HandleFeeRequest::new(
889889
native_runtime_config.clone(),
890890
state_root_hash,
@@ -894,15 +894,14 @@ pub fn execute_finalized_block(
894894
Box::new(initiator_addr.clone()),
895895
balance_identifier,
896896
BalanceIdentifier::Public(*(proposer.clone())),
897-
amount,
897+
fee_amount,
898898
),
899899
);
900900
scratch_state.handle_fee(handle_fee_request)
901901
}
902902
FeeHandling::Accumulate => {
903903
// in this mode, consumed gas is accumulated into a single purse
904904
// for later distribution
905-
let amount = artifact_builder.cost_to_use().saturating_sub(refund_amount);
906905
let handle_fee_request = HandleFeeRequest::new(
907906
native_runtime_config.clone(),
908907
state_root_hash,
@@ -912,7 +911,7 @@ pub fn execute_finalized_block(
912911
Box::new(initiator_addr.clone()),
913912
balance_identifier,
914913
BalanceIdentifier::Accumulate,
915-
amount,
914+
fee_amount,
916915
),
917916
);
918917
scratch_state.handle_fee(handle_fee_request)

node/src/components/contract_runtime/types.rs

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ pub(crate) struct ExecutionArtifactBuilder {
8282
refund: U512,
8383
size_estimate: u64,
8484
min_cost: U512,
85+
available: Option<U512>,
8586
}
8687

8788
impl ExecutionArtifactBuilder {
@@ -107,6 +108,7 @@ impl ExecutionArtifactBuilder {
107108
refund: U512::zero(),
108109
size_estimate: transaction.size_estimate() as u64,
109110
min_cost,
111+
available: None,
110112
}
111113
}
112114

@@ -130,6 +132,7 @@ impl ExecutionArtifactBuilder {
130132
refund: U512::zero(),
131133
size_estimate: transaction.size_estimate() as u64,
132134
min_cost: U512::zero(),
135+
available: None,
133136
}
134137
}
135138

@@ -149,14 +152,36 @@ impl ExecutionArtifactBuilder {
149152
self.consumed.value()
150153
}
151154

155+
pub fn available(&self) -> Option<U512> {
156+
self.available
157+
}
158+
159+
pub fn actual_cost(&self) -> U512 {
160+
self.cost
161+
}
162+
152163
pub fn cost_to_use(&self) -> U512 {
153164
// to prevent do-nothing exhaustion and other 0 cost scenarios,
154165
// we raise cost to min_cost if less than that
155-
let cost = self.cost;
156-
if cost < self.min_cost {
157-
self.min_cost
158-
} else {
159-
cost
166+
167+
let cost = {
168+
let cost = self.cost;
169+
if cost < self.min_cost {
170+
self.min_cost
171+
} else {
172+
cost
173+
}
174+
};
175+
176+
match self.available {
177+
Some(available) => {
178+
if available < self.cost {
179+
available
180+
} else {
181+
cost
182+
}
183+
}
184+
None => cost,
160185
}
161186
}
162187

@@ -352,11 +377,6 @@ impl ExecutionArtifactBuilder {
352377
Ok(self)
353378
}
354379

355-
pub fn with_cost(&mut self, new_cost: U512) -> &mut Self {
356-
self.cost = new_cost;
357-
self
358-
}
359-
360380
pub fn with_refund_amount(&mut self, refund: U512) -> &mut Self {
361381
self.refund = refund;
362382
self
@@ -440,6 +460,11 @@ impl ExecutionArtifactBuilder {
440460
self
441461
}
442462

463+
pub fn with_available(&mut self, available: Option<U512>) -> &mut Self {
464+
self.available = available;
465+
self
466+
}
467+
443468
pub(crate) fn build(self) -> ExecutionArtifact {
444469
let actual_cost = self.cost_to_use();
445470
let result = ExecutionResultV2 {

0 commit comments

Comments
 (0)