Skip to content

Commit 8ca56db

Browse files
committed
Implement the composed operation in Linera.
1 parent 7b6e921 commit 8ca56db

File tree

22 files changed

+219
-100
lines changed

22 files changed

+219
-100
lines changed

examples/counter/src/contract.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ impl Contract for CounterContract {
4545
self.state.value.set(value);
4646
}
4747

48-
async fn execute_operation(&mut self, operation: CounterOperation) -> u64 {
49-
let CounterOperation::Increment(operation) = operation;
50-
let new_value = self.state.value.get() + operation;
48+
async fn execute_operation(&mut self, operation: CounterOperation) -> CounterOperation {
49+
let CounterOperation::Increment(increment) = operation;
50+
let new_value = self.state.value.get() + increment;
5151
self.state.value.set(new_value);
52-
new_value
52+
operation
5353
}
5454

5555
async fn execute_message(&mut self, _message: ()) {
@@ -84,8 +84,8 @@ mod tests {
8484

8585
let expected_value = initial_value + increment;
8686

87-
assert_eq!(response, expected_value);
88-
assert_eq!(*counter.state.value.get(), initial_value + increment);
87+
assert_eq!(response, CounterOperation::Increment(increment));
88+
assert_eq!(*counter.state.value.get(), expected_value);
8989
}
9090

9191
#[test]
@@ -115,7 +115,7 @@ mod tests {
115115

116116
let expected_value = initial_value + increment;
117117

118-
assert_eq!(response, expected_value);
118+
assert_eq!(response, CounterOperation::Increment(increment));
119119
assert_eq!(*counter.state.value.get(), expected_value);
120120
}
121121

examples/counter/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ use serde::{Deserialize, Serialize};
1212

1313
pub struct CounterAbi;
1414

15-
#[derive(Debug, Deserialize, Serialize, GraphQLMutationRoot)]
15+
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, GraphQLMutationRoot)]
1616
pub enum CounterOperation {
1717
/// Increment the counter by the given value
1818
Increment(u64),
1919
}
2020

2121
impl ContractAbi for CounterAbi {
2222
type Operation = CounterOperation;
23-
type Response = u64;
23+
type Response = CounterOperation;
2424
}
2525

2626
impl ServiceAbi for CounterAbi {

linera-chain/src/block_tracker.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,13 +170,21 @@ impl<'resources, 'blobs> BlockExecutionTracker<'resources, 'blobs> {
170170

171171
/// Returns a new TransactionTracker for the current transaction.
172172
fn new_transaction_tracker(&mut self) -> Result<TransactionTracker, ChainError> {
173+
// Convert operation results to Vec<Vec<u8>>
174+
let previous_operation_results = self
175+
.operation_results
176+
.iter()
177+
.map(|result| result.0.clone())
178+
.collect();
179+
173180
Ok(TransactionTracker::new(
174181
self.local_time,
175182
self.transaction_index,
176183
self.next_application_index,
177184
self.next_chain_index,
178185
self.oracle_responses()?,
179186
&self.blobs,
187+
previous_operation_results,
180188
))
181189
}
182190

linera-chain/src/data_types.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,14 @@ impl From<&Operation> for OperationMetadata {
181181
},
182182
Operation::User {
183183
application_id,
184-
bytes,
184+
input,
185185
} => OperationMetadata {
186186
operation_type: "User".to_string(),
187187
application_id: Some(*application_id),
188-
user_bytes_hex: Some(hex::encode(bytes)),
188+
user_bytes_hex: Some(match input {
189+
linera_execution::OperationInput::Direct(bytes) => hex::encode(bytes),
190+
linera_execution::OperationInput::Composed => "composed".to_string(),
191+
}),
189192
system_bytes_hex: None,
190193
},
191194
}

linera-chain/src/unit_tests/chain_tests.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ use linera_execution::{
2626
committee::{Committee, ValidatorState},
2727
test_utils::{ExpectedCall, MockApplication},
2828
BaseRuntime, ContractRuntime, ExecutionError, ExecutionRuntimeConfig, ExecutionRuntimeContext,
29-
Operation, ResourceControlPolicy, ServiceRuntime, SystemOperation, TestExecutionRuntimeContext,
29+
Operation, OperationInput, ResourceControlPolicy, ServiceRuntime, SystemOperation,
30+
TestExecutionRuntimeContext,
3031
};
3132
use linera_views::{
3233
context::{Context as _, MemoryContext, ViewContext},
@@ -313,11 +314,11 @@ async fn test_application_permissions() -> anyhow::Result<()> {
313314
application.expect_call(ExpectedCall::default_finalize());
314315
let app_operation = Operation::User {
315316
application_id,
316-
bytes: b"foo".to_vec(),
317+
input: OperationInput::Direct(b"foo".to_vec()),
317318
};
318319
let another_app_operation = Operation::User {
319320
application_id: another_app_id,
320-
bytes: b"bar".to_vec(),
321+
input: OperationInput::Direct(b"bar".to_vec()),
321322
};
322323

323324
let valid_block = make_first_block(chain_id)
@@ -740,7 +741,7 @@ async fn prepare_test_with_dummy_mock_application(
740741

741742
let block = make_first_block(chain_id).with_operation(Operation::User {
742743
application_id,
743-
bytes: vec![],
744+
input: OperationInput::Direct(vec![]),
744745
});
745746

746747
Ok((application, application_id, chain, block, time))

linera-client/src/benchmark.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use linera_core::{
1919
client::{ChainClient, ChainClientError},
2020
Environment,
2121
};
22-
use linera_execution::{system::SystemOperation, Operation};
22+
use linera_execution::{system::SystemOperation, Operation, OperationInput};
2323
use linera_sdk::abis::fungible::FungibleOperation;
2424
use num_format::{Locale, ToFormattedString};
2525
use prometheus_parse::{HistogramCount, Scrape, Value};
@@ -730,7 +730,7 @@ impl<Env: Environment> Benchmark<Env> {
730730
.expect("should serialize fungible token operation");
731731
Operation::User {
732732
application_id,
733-
bytes,
733+
input: OperationInput::Direct(bytes),
734734
}
735735
}
736736
}

linera-core/src/unit_tests/wasm_client_tests.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,10 @@ where
166166

167167
let increment = 5_u64;
168168
let counter_operation = counter::CounterOperation::Increment(increment);
169+
let operation1 = Operation::user(application_id, &counter_operation)?;
170+
let operation2 = Operation::user_composed(application_id.forget_abi());
169171
creator
170-
.execute_operation(Operation::user(application_id, &counter_operation)?)
172+
.execute_operations(vec![operation1, operation2], vec![])
171173
.await
172174
.unwrap();
173175

@@ -177,9 +179,10 @@ where
177179
.await
178180
.unwrap();
179181

182+
// We do an increment by 5 and then immediately reiterate it.
180183
let expected = QueryOutcome {
181184
response: async_graphql::Response::new(
182-
async_graphql::Value::from_json(json!({"value": 15})).unwrap(),
185+
async_graphql::Value::from_json(json!({"value": 20})).unwrap(),
183186
),
184187
operations: vec![],
185188
};

linera-core/src/unit_tests/wasm_worker_tests.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ use linera_chain::{
2828
};
2929
use linera_execution::{
3030
system::SystemOperation, test_utils::SystemExecutionState, ExecutionRuntimeContext, Operation,
31-
OperationContext, ResourceController, TransactionTracker, WasmContractModule, WasmRuntime,
31+
OperationContext, OperationInput, ResourceController, TransactionTracker, WasmContractModule,
32+
WasmRuntime,
3233
};
3334
use linera_storage::{DbStorage, Storage};
3435
#[cfg(feature = "dynamodb")]
@@ -258,7 +259,7 @@ where
258259
.with_timestamp(3)
259260
.with_operation(Operation::User {
260261
application_id,
261-
bytes: user_operation.clone(),
262+
input: OperationInput::Direct(user_operation.clone()),
262263
});
263264
let operation_context = OperationContext {
264265
chain_id: creator_chain.id(),
@@ -273,7 +274,7 @@ where
273274
operation_context,
274275
Operation::User {
275276
application_id,
276-
bytes: user_operation,
277+
input: OperationInput::Direct(user_operation),
277278
},
278279
&mut TransactionTracker::new(
279280
Timestamp::from(3),
@@ -282,6 +283,7 @@ where
282283
0,
283284
Some(vec![OracleResponse::Blob(application_description_blob_id)]),
284285
&[],
286+
vec![],
285287
),
286288
&mut controller,
287289
)

linera-execution/src/evm/revm.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ use crate::{
3838
database::{DatabaseRuntime, StorageStats, EVM_SERVICE_GAS_LIMIT},
3939
},
4040
BaseRuntime, ContractRuntime, ContractSyncRuntimeHandle, DataBlobHash, EvmExecutionError,
41-
EvmRuntime, ExecutionError, ServiceRuntime, ServiceSyncRuntimeHandle, UserContract,
42-
UserContractInstance, UserContractModule, UserService, UserServiceInstance, UserServiceModule,
41+
EvmRuntime, ExecutionError, OperationInput, ServiceRuntime, ServiceSyncRuntimeHandle,
42+
UserContract, UserContractInstance, UserContractModule, UserService, UserServiceInstance,
43+
UserServiceModule,
4344
};
4445

4546
/// This is the selector of the `execute_message` that should be called
@@ -1449,7 +1450,8 @@ where
14491450
EvmQuery::Query(vec) => vec,
14501451
EvmQuery::Mutation(operation) => {
14511452
let mut runtime = self.db.runtime.lock().expect("The lock should be possible");
1452-
runtime.schedule_operation(operation)?;
1453+
let input = OperationInput::Direct(operation);
1454+
runtime.schedule_operation(input)?;
14531455
return Ok(Vec::new());
14541456
}
14551457
};

linera-execution/src/execution.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ where
132132
next_chain_index,
133133
None,
134134
&[],
135+
vec![], // No previous operation results for testing
135136
);
136137
txn_tracker.add_created_blob(blob);
137138
self.run_user_action(
@@ -310,8 +311,22 @@ where
310311
}
311312
Operation::User {
312313
application_id,
313-
bytes,
314+
input,
314315
} => {
316+
// Get the bytes for the operation based on the input type
317+
let bytes = match input {
318+
crate::OperationInput::Direct(bytes) => bytes.clone(),
319+
crate::OperationInput::Composed => {
320+
// For composed operations, use the result from the last operation
321+
let previous_results = txn_tracker.previous_operation_results();
322+
if previous_results.is_empty() {
323+
return Err(ExecutionError::ComposedOperationCannotBeFirst);
324+
}
325+
// Get the last operation result as input
326+
previous_results.last().unwrap().clone()
327+
}
328+
};
329+
315330
self.run_user_action(
316331
application_id,
317332
UserAction::Operation(context, bytes),

0 commit comments

Comments
 (0)