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

595 feature provide raw transaction data for emily api deposit operations #601

Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 27 additions & 12 deletions .generated-sources/emily/openapi/emily-openapi-spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -1203,8 +1203,8 @@
"required": [
"bitcoinTxid",
"bitcoinTxOutputIndex",
"reclaim",
"deposit"
"reclaimScript",
"depositScript"
],
"properties": {
"bitcoinTxOutputIndex": {
Expand All @@ -1217,11 +1217,11 @@
"type": "string",
"description": "Bitcoin transaction id."
},
"deposit": {
"depositScript": {
"type": "string",
"description": "Deposit script."
},
"reclaim": {
"reclaimScript": {
"type": "string",
"description": "Reclaim script."
}
Expand Down Expand Up @@ -1282,7 +1282,9 @@
"lastUpdateBlockHash",
"status",
"statusMessage",
"parameters"
"parameters",
"reclaimScript",
"depositScript"
],
"properties": {
"amount": {
Expand All @@ -1301,6 +1303,10 @@
"type": "string",
"description": "Bitcoin transaction id."
},
"depositScript": {
"type": "string",
"description": "Raw deposit script binary."
},
"fulfillment": {
"allOf": [
{
Expand All @@ -1326,6 +1332,10 @@
"type": "string",
"description": "Stacks address to received the deposited sBTC."
},
"reclaimScript": {
"type": "string",
"description": "Raw reclaim script binary."
},
"status": {
"$ref": "#/components/schemas/Status"
},
Expand All @@ -1345,7 +1355,9 @@
"amount",
"lastUpdateHeight",
"lastUpdateBlockHash",
"status"
"status",
"reclaimScript",
"depositScript"
],
"properties": {
"amount": {
Expand All @@ -1364,6 +1376,10 @@
"type": "string",
"description": "Bitcoin transaction id."
},
"depositScript": {
"type": "string",
"description": "Raw deposit script binary."
},
"lastUpdateBlockHash": {
"type": "string",
"description": "The most recent Stacks block hash the API was aware of when the deposit was last\nupdated. If the most recent update is tied to an artifact on the Stacks blockchain\nthen this hash is the Stacks block hash that contains that artifact."
Expand All @@ -1378,6 +1394,10 @@
"type": "string",
"description": "Stacks address to received the deposited sBTC."
},
"reclaimScript": {
"type": "string",
"description": "Raw reclaim script binary."
},
"status": {
"$ref": "#/components/schemas/Status"
}
Expand All @@ -1388,8 +1408,7 @@
"description": "Deposit parameters.",
"required": [
"maxFee",
"lockTime",
"reclaimScript"
"lockTime"
],
"properties": {
"lockTime": {
Expand All @@ -1403,10 +1422,6 @@
"format": "int64",
"description": "Maximum fee the signers are allowed to take from the deposit to facilitate\nthe transaction.",
"minimum": 0
},
"reclaimScript": {
"type": "string",
"description": "Raw reclaim script."
}
}
},
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ EMILY_CDK_SOURCE_FILES := $(wildcard $(subst dir, emily/bin/lib, $(FIVE_DIRS_DEE

$(EMILY_CDK_TEMPLATE): $(INSTALL_TARGET) $(EMILY_OPENAPI_SPEC) $(EMILY_CDK_SOURCE_FILES)
AWS_STAGE=local \
TABLES_ONLY=true \
pnpm --filter $(EMILY_CDK_PROJECT_NAME) run synth

# Emily Handler --------------------------------------
Expand Down Expand Up @@ -234,4 +235,3 @@ run-signer:
done; \
echo $$POSTGRES_PORT; \
RUST_LOG=debug SIGNER_SIGNER__DB_ENDPOINT="postgres://postgres:postgres@localhost:$$POSTGRES_PORT/signer" cargo run --bin signer -- -c ./signer/src/config/default.toml --migrate-db

6 changes: 5 additions & 1 deletion devenv/aws-setup/initialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,12 @@ def replace_local_lambda_path(template, local_lambda_path):
modified_template, "AWS::Lambda::Function")

# Ensure there's exactly one lambda function in the template.
if len(lambda_template_resource_ids) == 0:
print(f"Not making any lambda changes because no Lambda functions were found.")
return
if len(lambda_template_resource_ids) != 1:
print(f"{len(lambda_template_resource_ids)} Lambda functions found, but there must be exactly 1.")
print(f"{len(lambda_template_resource_ids)} Lambda functions found, but this script supports at most 1. Failing...")
print(f"Lambda resource ids: {lambda_template_resource_ids}")
exit(1)

# Update lambda local code path.
Expand Down
13 changes: 13 additions & 0 deletions emily/cdk/lib/emily-stack-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ export class EmilyStackUtils {
*/
private static awsRegion?: string;

/*
* Whether only tables should be deployed.
*/
private static tablesOnly?: boolean;

/*
* Returns the current stage name.
*/
Expand Down Expand Up @@ -64,6 +69,14 @@ export class EmilyStackUtils {
return this.awsRegion;
}

/*
* Returns whether only tables should be deployed.
*/
public static isTablesOnly(): boolean {
this.tablesOnly ??= (process.env.TABLES_ONLY ?? "false").toLowerCase() === "true";
return this.tablesOnly;
}

/*
* Return the path to the resource where the path provided to the input is the
* path from workspace root.
Expand Down
26 changes: 15 additions & 11 deletions emily/cdk/lib/emily-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,21 @@ export class EmilyStack extends cdk.Stack {
chainstateTableName,
);

const operationLambda: lambda.Function = this.createOrUpdateOperationLambda(
depositTableName,
withdrawalTableName,
chainstateTableName,
props
);
if (!EmilyStackUtils.isTablesOnly()) {
const operationLambda: lambda.Function = this.createOrUpdateOperationLambda(
depositTableName,
withdrawalTableName,
chainstateTableName,
props
);

// Give the operation lambda full access to the DynamoDB tables.
depositTable.grantReadWriteData(operationLambda);
withdrawalTable.grantReadWriteData(operationLambda);
chainstateTable.grantReadWriteData(operationLambda);
// Give the operation lambda full access to the DynamoDB tables.
depositTable.grantReadWriteData(operationLambda);
withdrawalTable.grantReadWriteData(operationLambda);
chainstateTable.grantReadWriteData(operationLambda);

const emilyApi: apig.SpecRestApi = this.createOrUpdateApi(operationLambda, props);
const emilyApi: apig.SpecRestApi = this.createOrUpdateApi(operationLambda, props);
}
Comment on lines +48 to +62
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Prevents the missing bootstrap.zip case when running the makefile command.

}

/**
Expand Down Expand Up @@ -101,6 +103,8 @@ export class EmilyStack extends cdk.Stack {
"Recipient",
"Amount",
"LastUpdateBlockHash",
"ReclaimScript",
"DepositScript",
]
});

Expand Down
7 changes: 3 additions & 4 deletions emily/handler/src/api/handlers/deposit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,7 @@ pub async fn create_deposit(
bitcoin_txid: body.bitcoin_txid,
bitcoin_tx_output_index: body.bitcoin_tx_output_index,
},
parameters: DepositParametersEntry {
reclaim_script: body.reclaim,
..Default::default()
},
parameters: DepositParametersEntry { ..Default::default() },
history: vec![DepositEvent {
status: StatusEntry::Pending,
message: "Just received deposit".to_string(),
Expand All @@ -227,6 +224,8 @@ pub async fn create_deposit(
status,
last_update_block_hash: stacks_block_hash,
last_update_height: stacks_block_height,
reclaim_script: body.reclaim_script,
deposit_script: body.deposit_script,
..Default::default()
};
// Validate deposit entry.
Expand Down
14 changes: 12 additions & 2 deletions emily/handler/src/api/models/deposit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ pub struct Deposit {
pub status_message: String,
/// Deposit parameters
pub parameters: DepositParameters,
/// Raw reclaim script binary.
pub reclaim_script: String,
/// Raw deposit script binary.
pub deposit_script: String,
Copy link
Collaborator

Choose a reason for hiding this comment

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

qq: I was looking around and noticed that those scripts, as well as things like bitcoin_txid, are Strings; and I didn't see any reference to specific encodings used (eg, hex or b64). So, if those are just normal strings, don't we risk to break everything if the raw binary is not utf8-friendly?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah this isn't specified in the spec either. Can we make this a hex string?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This will only be a comment change for now since these aren't being messed with.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done. Changed the comment to the following:

    /// Raw reclaim script binary in hex.
    pub reclaim_script: String,
    /// Raw deposit script binary in hex.
    pub deposit_script: String,

Copy link
Contributor

Choose a reason for hiding this comment

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

That's cool see. I guess that means that we require the input be a hex string. Should we clarify that in an addendum to the spec, or just update it as is now?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

update as it is now

/// Details about the on chain artifacts that fulfilled the deposit.
#[serde(skip_serializing_if = "Option::is_none")]
pub fulfillment: Option<Fulfillment>,
Expand Down Expand Up @@ -76,8 +80,8 @@ pub struct DepositParameters {
pub max_fee: u64,
/// Bitcoin block height at which the reclaim script becomes executable.
pub lock_time: u64,
/// Raw reclaim script.
pub reclaim_script: String,
// /// Raw reclaim script.
// pub reclaim_script: String,
matteojug marked this conversation as resolved.
Show resolved Hide resolved
}

/// Reduced version of the Deposit data.
Expand Down Expand Up @@ -115,6 +119,10 @@ pub struct DepositInfo {
pub last_update_block_hash: String,
/// The status of the deposit.
pub status: Status,
/// Raw reclaim script binary.
pub reclaim_script: String,
/// Raw deposit script binary.
pub deposit_script: String,
}

/// Create a DepositInfo, which has a subset of the data within a Deposit, from a Deposit.
Expand All @@ -128,6 +136,8 @@ impl From<Deposit> for DepositInfo {
last_update_height: deposit.last_update_height,
last_update_block_hash: deposit.last_update_block_hash,
status: deposit.status,
reclaim_script: deposit.reclaim_script,
deposit_script: deposit.deposit_script,
}
}
}
4 changes: 2 additions & 2 deletions emily/handler/src/api/models/deposit/requests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ pub struct CreateDepositRequestBody {
/// Output index on the bitcoin transaction associated with this specific deposit.
pub bitcoin_tx_output_index: u32,
/// Reclaim script.
pub reclaim: String,
pub reclaim_script: String,
/// Deposit script.
pub deposit: String,
pub deposit_script: String,
}

/// A singlular Deposit update that contains only the fields pertinent
Expand Down
15 changes: 12 additions & 3 deletions emily/handler/src/database/entries/deposit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ pub struct DepositEntry {
/// The status of the deposit.
#[serde(rename = "OpStatus")]
pub status: Status,
/// The raw reclaim script.
pub reclaim_script: String,
/// The raw deposit script.
pub deposit_script: String,
/// The most recent Stacks block height the API was aware of when the deposit was last
/// updated. If the most recent update is tied to an artifact on the Stacks blockchain
/// then this height is the Stacks block height that contains that artifact.
Expand Down Expand Up @@ -235,8 +239,9 @@ impl TryFrom<DepositEntry> for Deposit {
parameters: DepositParameters {
max_fee: deposit_entry.parameters.max_fee,
lock_time: deposit_entry.parameters.lock_time,
reclaim_script: deposit_entry.parameters.reclaim_script,
},
reclaim_script: deposit_entry.reclaim_script,
deposit_script: deposit_entry.deposit_script,
fulfillment,
})
}
Expand All @@ -251,8 +256,6 @@ pub struct DepositParametersEntry {
pub max_fee: u64,
/// Bitcoin block height at which the reclaim script becomes executable.
pub lock_time: u64,
/// Raw reclaim script.
pub reclaim_script: String,
}

/// Event in the history of a deposit.
Expand Down Expand Up @@ -334,6 +337,10 @@ pub struct DepositInfoEntry {
pub recipient: String,
/// Amount of BTC being deposited in satoshis.
pub amount: u64,
/// The raw reclaim script.
pub reclaim_script: String,
/// The raw deposit script.
pub deposit_script: String,
/// The most recent Stacks block hash the API was aware of when the deposit was last
/// updated. If the most recent update is tied to an artifact on the Stacks blockchain
/// then this hash is the Stacks block hash that contains that artifact.
Expand Down Expand Up @@ -387,6 +394,8 @@ impl From<DepositInfoEntry> for DepositInfo {
last_update_height: deposit_info_entry.key.last_update_height,
last_update_block_hash: deposit_info_entry.last_update_block_hash,
status: deposit_info_entry.key.status,
reclaim_script: deposit_info_entry.reclaim_script,
deposit_script: deposit_info_entry.deposit_script,
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions emily/handler/tests/integration/complex/reorg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ async fn simple_reorg_test_base(scenario: ReorgScenario) {
let deposit_request = CreateDepositRequestBody {
bitcoin_txid: format!("{TEST_BITCOIN_TXID}-{stacks_block_height}"),
bitcoin_tx_output_index: 1,
reclaim: TEST_RECLAIM_SCRIPT.to_string(),
deposit: TEST_DEPOSIT_SCRIPT.to_string(),
reclaim_script: TEST_RECLAIM_SCRIPT.to_string(),
deposit_script: TEST_DEPOSIT_SCRIPT.to_string(),
};
let withdrawal_request = CreateWithdrawalRequestBody {
request_id: stacks_block_height,
Expand Down
14 changes: 7 additions & 7 deletions emily/handler/tests/integration/endpoints/deposit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use emily_handler::{
deposit::{
requests::{CreateDepositRequestBody, DepositUpdate, UpdateDepositsRequestBody},
responses::{GetDepositsForTransactionResponse, GetDepositsResponse},
Deposit, DepositInfo, DepositParameters,
Deposit, DepositInfo,
},
},
context::EmilyContext,
Expand All @@ -23,6 +23,8 @@ use std::sync::LazyLock;
use tokio;

const TEST_BLOCK_HEIGHT: u64 = 123;
const TEST_RECLAIM_SCRIPT: &str = "example_reclaim_script";
const TEST_DEPOSIT_SCRIPT: &str = "example_deposit_script";

/// Contains data about a deposit transaction used for testing so that
/// all the tests have a common understanding of the deposits in the
Expand Down Expand Up @@ -78,8 +80,8 @@ async fn setup_deposit_integration_test() -> TestClient {
let request: CreateDepositRequestBody = serde_json::from_value(json!({
"bitcoinTxid": bitcoin_txid.clone(),
"bitcoinTxOutputIndex": bitcoin_tx_output_index,
"reclaim": "example_reclaim_script",
"deposit": "example_deposit_script",
"reclaimScript": TEST_RECLAIM_SCRIPT.to_string(),
"depositScript": TEST_DEPOSIT_SCRIPT.to_string(),
}))
.expect("Failed to deserialize create deposit request body in test setup");
let response = client.create_deposit(&request).await;
Expand Down Expand Up @@ -117,10 +119,8 @@ fn just_created_deposit(bitcoin_txid: String, bitcoin_tx_output_index: u32) -> D
last_update_block_hash: "DUMMY_HASH".to_string(),
last_update_height: TEST_BLOCK_HEIGHT,
status_message: "Just received deposit".to_string(),
parameters: DepositParameters {
reclaim_script: "example_reclaim_script".to_string(),
..Default::default()
},
reclaim_script: TEST_RECLAIM_SCRIPT.to_string(),
deposit_script: TEST_DEPOSIT_SCRIPT.to_string(),
..Default::default()
}
}
Expand Down
4 changes: 2 additions & 2 deletions emily/handler/tests/integration/populate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ async fn create_deposits(client: &TestClient) {
let create_request = CreateDepositRequestBody {
bitcoin_txid: format!("txid-{i}"),
bitcoin_tx_output_index: j + offset,
reclaim: format!("reclaim-script-{i}"),
deposit: format!("deposit-script-{i}"),
reclaim_script: format!("reclaim-script-{i}"),
deposit_script: format!("deposit-script-{i}"),
};
client.create_deposit(&create_request).await;
}
Expand Down
Loading
Loading