diff --git a/.github/workflows/bitcoin-tests.yml b/.github/workflows/bitcoin-tests.yml index ff7a0dd3d..05da90786 100644 --- a/.github/workflows/bitcoin-tests.yml +++ b/.github/workflows/bitcoin-tests.yml @@ -50,6 +50,7 @@ jobs: - tests::neon_integrations::filter_long_runtime_tx_integration_test - tests::neon_integrations::mining_transactions_is_fair steps: + - uses: actions/checkout@v2 - name: Download docker image uses: actions/download-artifact@v2 with: @@ -74,6 +75,7 @@ jobs: - tests::neon_integrations::atlas_integration_test - tests::neon_integrations::atlas_stress_integration_test steps: + - uses: actions/checkout@v2 - name: Download docker image uses: actions/download-artifact@v2 with: diff --git a/docs/rpc/api/core-node/post-fee-transaction-response.example.json b/docs/rpc/api/core-node/post-fee-transaction-response.example.json index ebcc331c1..f78b80eb7 100644 --- a/docs/rpc/api/core-node/post-fee-transaction-response.example.json +++ b/docs/rpc/api/core-node/post-fee-transaction-response.example.json @@ -8,14 +8,14 @@ "write_length": 1020 }, "estimated_cost_scalar": 14, - "estimated_fee_rates": { - "high": 10, - "low": 1.2410714285714286, - "middle": 8.958333333333332 - }, - "estimated_fees": { - "high": 140, - "low": 17, - "middle": 125 - } + "estimated_fee_rates": [ + 1.2410714285714286, + 8.958333333333332, + 10 + ], + "estimated_fees": [ + 17, + 125, + 140 + ] } diff --git a/docs/rpc/api/core-node/post-fee-transaction-response.schema.json b/docs/rpc/api/core-node/post-fee-transaction-response.schema.json index 34192f491..8ddbdd0d1 100644 --- a/docs/rpc/api/core-node/post-fee-transaction-response.schema.json +++ b/docs/rpc/api/core-node/post-fee-transaction-response.schema.json @@ -25,23 +25,15 @@ } }, "estimated_fee_rates": { - "type": "object", - "additionalProperties": false, - "required": ["high", "low", "middle"], - "properties": { - "high": { "type": "number" }, - "low": { "type": "number" }, - "middle": { "type": "number" } + "type": "array", + "items": { + "type": "number" } }, "estimated_fees": { - "type": "object", - "additionalProperties": false, - "required": ["high", "low", "middle"], - "properties": { - "high": { "type": "integer" }, - "low": { "type": "integer" }, - "middle": { "type": "integer" } + "type": "array", + "items": { + "type": "integer" } } } diff --git a/docs/rpc/openapi.yaml b/docs/rpc/openapi.yaml index ead330437..47acd3060 100644 --- a/docs/rpc/openapi.yaml +++ b/docs/rpc/openapi.yaml @@ -322,7 +322,6 @@ paths: `fee_rate` x `cost_scalar_change_by_byte` x (`final_size` - `estimated_size`) - description: operationId: post_fee_transaction requestBody: content: diff --git a/src/cost_estimates/mod.rs b/src/cost_estimates/mod.rs index a1bb700e9..80c39c970 100644 --- a/src/cost_estimates/mod.rs +++ b/src/cost_estimates/mod.rs @@ -65,6 +65,12 @@ fn saturating_f64_math(res: f64) -> f64 { } } +impl FeeRateEstimate { + pub fn to_vec(self) -> Vec { + vec![self.low, self.middle, self.high] + } +} + impl Mul for FeeRateEstimate { type Output = FeeRateEstimate; diff --git a/src/cost_estimates/tests/cost_estimators.rs b/src/cost_estimates/tests/cost_estimators.rs index a9f294165..482788d35 100644 --- a/src/cost_estimates/tests/cost_estimators.rs +++ b/src/cost_estimates/tests/cost_estimators.rs @@ -49,6 +49,10 @@ impl CostMetric for TestCostMetric { fn from_len(&self, _tx_len: u64) -> u64 { 1 } + + fn change_per_byte(&self) -> f64 { + 0f64 + } } #[test] diff --git a/src/cost_estimates/tests/fee_scalar.rs b/src/cost_estimates/tests/fee_scalar.rs index 7a72ab8b6..12eb2a5ca 100644 --- a/src/cost_estimates/tests/fee_scalar.rs +++ b/src/cost_estimates/tests/fee_scalar.rs @@ -47,6 +47,10 @@ impl CostMetric for TestCostMetric { fn from_len(&self, _tx_len: u64) -> u64 { 1 } + + fn change_per_byte(&self) -> f64 { + 0f64 + } } #[test] diff --git a/src/net/mod.rs b/src/net/mod.rs index c11eee603..0e6ba04a0 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -1043,14 +1043,18 @@ impl RPCFeeEstimate { low: estimated_fees_f64.low as u64, } } + + pub fn to_vec(self) -> Vec { + vec![self.low, self.middle, self.high] + } } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct RPCFeeEstimateResponse { pub estimated_cost: ExecutionCost, pub estimated_cost_scalar: u64, - pub estimated_fees: RPCFeeEstimate, - pub estimated_fee_rates: FeeRateEstimate, + pub estimated_fees: Vec, + pub estimated_fee_rates: Vec, pub cost_scalar_change_by_byte: f64, } diff --git a/src/net/rpc.rs b/src/net/rpc.rs index 93cc2fd37..0277ebb68 100644 --- a/src/net/rpc.rs +++ b/src/net/rpc.rs @@ -1631,7 +1631,8 @@ impl ConversationHttp { } }; - let estimated_fees = RPCFeeEstimate::estimate_fees(scalar_cost, fee_rates.clone()); + let estimated_fees = + RPCFeeEstimate::estimate_fees(scalar_cost, fee_rates.clone()).to_vec(); let response = HttpResponseType::TransactionFeeEstimation( response_metadata, @@ -1639,7 +1640,7 @@ impl ConversationHttp { estimated_cost, estimated_fees, estimated_cost_scalar: scalar_cost, - estimated_fee_rates: fee_rates, + estimated_fee_rates: fee_rates.to_vec(), cost_scalar_change_by_byte: metric.change_per_byte(), }, ); diff --git a/testnet/stacks-node/src/tests/integrations.rs b/testnet/stacks-node/src/tests/integrations.rs index c7e37c166..f9de0bc43 100644 --- a/testnet/stacks-node/src/tests/integrations.rs +++ b/testnet/stacks-node/src/tests/integrations.rs @@ -856,15 +856,16 @@ fn integration_test_get_info() { // the estimated scalar should still be non-zero, because the length of the tx goes into this field. assert!(res.get("estimated_cost_scalar").unwrap().as_u64().unwrap() > 0); - let estimated_fee_rates = res.get("estimated_fee_rates").expect("Should have an estimated_fee_rates field"); - let estimated_fees = res.get("estimated_fees").expect("Should have an estimated_fees field"); - assert!(estimated_fee_rates.get("high").is_some(), "Should have 'high' field"); - assert!(estimated_fee_rates.get("low").is_some(), "Should have 'low' field"); - assert!(estimated_fee_rates.get("middle").is_some(), "Should have 'middle' field"); - assert!(estimated_fees.get("high").is_some(), "Should have 'high' field"); - assert!(estimated_fees.get("low").is_some(), "Should have 'low' field"); - assert!(estimated_fees.get("middle").is_some(), "Should have 'middle' field"); + let estimated_fee_rates = res.get("estimated_fee_rates").expect("Should have an estimated_fee_rates field") + .as_array() + .expect("Fees should be array"); + let estimated_fees = res.get("estimated_fees").expect("Should have an estimated_fees field") + .as_array() + .expect("Fees should be array"); + + assert!(estimated_fee_rates.len() == 3, "Fee rates should be length 3 array"); + assert!(estimated_fees.len() == 3, "Fees should be length 3 array"); let tx_payload = TransactionPayload::from(TransactionContractCall { address: contract_addr.clone(), @@ -901,15 +902,15 @@ fn integration_test_get_info() { let estimated_cost_scalar = res.get("estimated_cost_scalar").unwrap().as_u64().unwrap(); assert!(estimated_cost_scalar > 0); - let estimated_fee_rates = res.get("estimated_fee_rates").expect("Should have an estimated_fee_rates field"); - let estimated_fees = res.get("estimated_fees").expect("Should have an estimated_fees field"); + let estimated_fee_rates = res.get("estimated_fee_rates").expect("Should have an estimated_fee_rates field") + .as_array() + .expect("Fees should be array"); + let estimated_fees = res.get("estimated_fees").expect("Should have an estimated_fees field") + .as_array() + .expect("Fees should be array"); - assert!(estimated_fee_rates.get("high").is_some(), "Should have 'high' field"); - assert!(estimated_fee_rates.get("low").is_some(), "Should have 'low' field"); - assert!(estimated_fee_rates.get("middle").is_some(), "Should have 'middle' field"); - assert!(estimated_fees.get("high").is_some(), "Should have 'high' field"); - assert!(estimated_fees.get("low").is_some(), "Should have 'low' field"); - assert!(estimated_fees.get("middle").is_some(), "Should have 'middle' field"); + assert!(estimated_fee_rates.len() == 3, "Fee rates should be length 3 array"); + assert!(estimated_fees.len() == 3, "Fees should be length 3 array"); let tx_payload = TransactionPayload::from(TransactionContractCall { address: contract_addr.clone(), @@ -946,13 +947,15 @@ fn integration_test_get_info() { assert!(estimated_cost_scalar > 0); assert!(new_estimated_cost_scalar > estimated_cost_scalar, "New scalar estimate should be higher because of the tx length increase"); - let new_estimated_fees = res.get("estimated_fees").expect("Should have an estimated_fees field"); + let new_estimated_fees = res.get("estimated_fees").expect("Should have an estimated_fees field") + .as_array() + .expect("Fees should be array"); - assert!(new_estimated_fees.get("high").unwrap().as_u64().unwrap() >= estimated_fees.get("high").unwrap().as_u64().unwrap(), + assert!(new_estimated_fees[2].as_u64().unwrap() >= estimated_fees[2].as_u64().unwrap(), "Supplying an estimated tx length should increase the estimated fees"); - assert!(new_estimated_fees.get("low").unwrap().as_u64().unwrap() >= estimated_fees.get("low").unwrap().as_u64().unwrap(), + assert!(new_estimated_fees[0].as_u64().unwrap() >= estimated_fees[0].as_u64().unwrap(), "Supplying an estimated tx length should increase the estimated fees"); - assert!(new_estimated_fees.get("middle").unwrap().as_u64().unwrap() >= estimated_fees.get("middle").unwrap().as_u64().unwrap(), + assert!(new_estimated_fees[1].as_u64().unwrap() >= estimated_fees[1].as_u64().unwrap(), "Supplying an estimated tx length should increase the estimated fees"); }, _ => {},