Skip to content

Commit

Permalink
More cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
lrubasze committed Nov 21, 2024
1 parent 46cebc9 commit d37c370
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 65 deletions.
1 change: 1 addition & 0 deletions core-rust/mesh-api-server/mesh-cli-configs/workflows.ros
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ radix_workflow(1){
currency = {"symbol":"resource_loc1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxvq32hv", "decimals":18};
min_balance = "1111000000000000000000";

// sender account is the one of the prefunded_accounts
sender = find_balance({
"minimum_balance":{
"value": {{min_balance}},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ pub fn extract_radix_account_address_from_account_identifier(
Ok(component_address)
} else {
Err(ExtractionError::InvalidAccount {
message: format!("address {} is not an account", account_identifier.address),
message: format!("Whilst this API returns balance changes with an `AccountIdentifier` representing any global entity to allow full reconciliation, only Radix account addresses starting `account_` are accepted for the construction and account balance endpoints. {} is not a Radix account.", account_identifier.address),
})
}
}
35 changes: 17 additions & 18 deletions core-rust/mesh-api-server/src/mesh_api/handlers/account_balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,6 @@ pub(crate) async fn handle_account_balance(
read_current_ledger_header(database.deref())
};

let type_info: Option<TypeInfoSubstate> = read_optional_substate::<TypeInfoSubstate>(
database.deref(),
component_address.as_node_id(),
TYPE_INFO_FIELD_PARTITION,
&TypeInfoField::TypeInfo.into(),
);

if type_info.is_none() {
return Ok(Json(models::AccountBalanceResponse {
block_identifier: Box::new(to_mesh_api_block_identifier_from_ledger_header(
&header.into(),
)?),
balances: vec![],
metadata: None,
}));
}

let balances = match request.currencies {
Some(currencies) => {
let resources = currencies
Expand All @@ -62,7 +45,23 @@ pub(crate) async fn handle_account_balance(
&resources,
)?
}
None => get_all_balances(&mapping_context, database.deref(), &component_address)?,
None => {
// Check if account is instantiated
let type_info: Option<TypeInfoSubstate> = read_optional_substate::<TypeInfoSubstate>(
database.deref(),
component_address.as_node_id(),
TYPE_INFO_FIELD_PARTITION,
&TypeInfoField::TypeInfo.into(),
);

if type_info.is_some() {
get_all_balances(&mapping_context, database.deref(), &component_address)?
} else {
// We expect empty balances vector here, but let the `get_requested_balances()`
// deal with this.
get_requested_balances(&mapping_context, database.deref(), &component_address, &[])?
}
}
};

// see https://docs.cdp.coinbase.com/mesh/docs/models#accountbalanceresponse for field
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub(crate) async fn handle_construction_payloads(
assert_matching_network(&request.network_identifier, &state.network)?;

let public_keys = request.public_keys.unwrap_or_default();
let public_key = if public_keys.len() == 1 {
let signer_public_key = if public_keys.len() == 1 {
extract_public_key(&public_keys[0]).map_err(|e| e.into_response_error("public_key"))?
} else {
return Err(
Expand All @@ -20,14 +20,15 @@ pub(crate) async fn handle_construction_payloads(
)),
);
};
let signature_type = match &public_key {
let signature_type = match &signer_public_key {
PublicKey::Secp256k1(_) => SignatureType::EcdsaRecovery,
PublicKey::Ed25519(_) => SignatureType::Ed25519,
};
let account_address = ComponentAddress::preallocated_account_from_public_key(&public_key);
let account_identifier = to_api_account_identifier_from_public_key(
let signer_account_address =
ComponentAddress::preallocated_account_from_public_key(&signer_public_key);
let signer_account_identifier = to_api_account_identifier_from_public_key(
&MappingContext::new(&state.network),
public_key,
signer_public_key,
)?;

let metadata: ConstructionMetadata = request
Expand All @@ -40,7 +41,7 @@ pub(crate) async fn handle_construction_payloads(
)?;

let extraction_context = ExtractionContext::new(&state.network);
let mut builder = ManifestBuilder::new().lock_fee(account_address, dec!(10));
let mut builder = ManifestBuilder::new().lock_fee(signer_account_address, dec!(10));
for operation in request.operations {
let operation_type =
MeshApiOperationType::from_str(operation._type.as_str()).map_err(|_| {
Expand Down Expand Up @@ -82,58 +83,44 @@ pub(crate) async fn handle_construction_payloads(
}
}
let manifest = builder.build();

let intent = IntentV1 {
header: TransactionHeaderV1 {
network_id: state.network.id,
start_epoch_inclusive: Epoch::of(metadata.start_epoch_inclusive),
end_epoch_exclusive: Epoch::of(metadata.end_epoch_exclusive),
nonce: metadata.intent_discriminator,
notary_public_key: public_key,
notary_is_signatory: true,
tip_percentage: metadata.tip_percentage,
let signed_intent = SignedIntentV1 {
intent: IntentV1 {
header: TransactionHeaderV1 {
network_id: state.network.id,
start_epoch_inclusive: Epoch::of(metadata.start_epoch_inclusive),
end_epoch_exclusive: Epoch::of(metadata.end_epoch_exclusive),
nonce: metadata.intent_discriminator,
notary_public_key: signer_public_key,
notary_is_signatory: true,
tip_percentage: metadata.tip_percentage,
},
instructions: InstructionsV1(manifest.instructions),
blobs: BlobsV1 {
blobs: Default::default(),
},
message: MessageV1::None,
},
instructions: InstructionsV1(manifest.instructions),
blobs: BlobsV1 {
blobs: Default::default(),
intent_signatures: IntentSignaturesV1 {
signatures: Default::default(),
},
message: MessageV1::None,
};
let signed_intent_bytes = signed_intent.to_raw().unwrap();

let intent_bytes = intent.to_raw().unwrap();
let intent_hash = PreparedIntentV1::prepare(&intent_bytes, &PreparationSettings::latest())
.unwrap()
.transaction_intent_hash();
let intent_signatures_hash = hash_encoded_sbor_value(&IntentSignaturesV1 {
signatures: Default::default(),
});
let signed_intent_hash = SignedTransactionIntentHash::from_hash(hash(
[
[
TRANSACTION_HASHABLE_PAYLOAD_PREFIX,
TransactionDiscriminator::V1SignedIntent as u8,
]
.as_slice(),
intent_hash.0.as_slice(),
intent_signatures_hash.0.as_slice(),
]
.concat(),
));
let signed_transaction_intent_hash =
PreparedSignedIntentV1::prepare(&signed_intent_bytes, &PreparationSettings::latest())
.expect("Signed intent could be prepared")
.signed_transaction_intent_hash();
let intent_bytes = signed_intent.intent.to_raw().unwrap();

// See https://docs.cdp.coinbase.com/mesh/docs/models#constructionpayloadsresponse for field
// definitions
Ok(Json(models::ConstructionPayloadsResponse {
unsigned_transaction: intent_bytes.to_hex(),
payloads: vec![SigningPayload {
address: None, // deprecated
account_identifier: Some(Box::new(account_identifier)),
hex_bytes: hex::encode(signed_intent_hash.as_bytes()),
account_identifier: Some(Box::new(signer_account_identifier)),
hex_bytes: hex::encode(signed_transaction_intent_hash.as_bytes()),
signature_type: Some(signature_type),
}],
}))
}

fn hash_encoded_sbor_value<T: ManifestEncode>(value: T) -> Hash {
// Ignore the version byte
hash(&manifest_encode(&value).unwrap()[1..])
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ pub(crate) async fn handle_construction_preprocess(
) -> Result<Json<models::ConstructionPreprocessResponse>, ResponseError> {
assert_matching_network(&request.network_identifier, &state.network)?;

// We assume that the withdrawing account (sender) will
// - cover the transaction fee
// - sign the transaction
// Add it to the required_public_keys vector.
let mut senders = Vec::new();
for operation in request.operations {
let operation_type =
Expand Down

0 comments on commit d37c370

Please sign in to comment.