Skip to content

Commit

Permalink
Add a transaction context function to get the raw transaction hash
Browse files Browse the repository at this point in the history
This commit adds a transaction context function to get the raw transaction hash.
  • Loading branch information
junkil-park committed Oct 3, 2024
1 parent 514653c commit fa93aa3
Show file tree
Hide file tree
Showing 8 changed files with 206 additions and 35 deletions.
41 changes: 38 additions & 3 deletions aptos-move/aptos-vm/src/transaction_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
// Parts of the project are originally copyright © Meta Platforms, Inc.
// SPDX-License-Identifier: Apache-2.0

use aptos_crypto::HashValue;
use aptos_crypto::{hash::CryptoHash, HashValue};
use aptos_gas_algebra::{FeePerGasUnit, Gas, NumBytes};
use aptos_types::{
account_address::AccountAddress,
chain_id::ChainId,
transaction::{
user_transaction_context::UserTransactionContext, EntryFunction, Multisig,
SignedTransaction, TransactionPayload,
authenticator::TransactionAuthenticator::{FeePayer, MultiAgent},
user_transaction_context::UserTransactionContext,
EntryFunction, Multisig, RawTransactionWithData, SignedTransaction, TransactionPayload,
},
};

Expand All @@ -31,6 +32,7 @@ pub struct TransactionMetadata {
pub is_keyless: bool,
pub entry_function_payload: Option<EntryFunction>,
pub multisig_payload: Option<Multisig>,
pub raw_transaction_hash: Vec<u8>,
}

impl TransactionMetadata {
Expand Down Expand Up @@ -89,6 +91,34 @@ impl TransactionMetadata {
TransactionPayload::Multisig(m) => Some(m.clone()),
_ => None,
},
raw_transaction_hash: match txn.authenticator_ref() {

Check warning on line 94 in aptos-move/aptos-vm/src/transaction_metadata.rs

View check run for this annotation

Codecov / codecov/patch

aptos-move/aptos-vm/src/transaction_metadata.rs#L94

Added line #L94 was not covered by tests
MultiAgent {
sender: _,
secondary_signer_addresses,
secondary_signers: _,
} => {
let raw_txn = RawTransactionWithData::new_multi_agent(
txn.clone().into_raw_transaction(),
secondary_signer_addresses.clone(),
);
raw_txn.hash().to_vec()

Check warning on line 104 in aptos-move/aptos-vm/src/transaction_metadata.rs

View check run for this annotation

Codecov / codecov/patch

aptos-move/aptos-vm/src/transaction_metadata.rs#L97-L104

Added lines #L97 - L104 were not covered by tests
},
FeePayer {
sender: _,
secondary_signer_addresses,
secondary_signers: _,
fee_payer_address,
fee_payer_signer: _,
} => {
let raw_txn = RawTransactionWithData::new_fee_payer(
txn.clone().into_raw_transaction(),
secondary_signer_addresses.clone(),
*fee_payer_address,
);
raw_txn.hash().to_vec()

Check warning on line 118 in aptos-move/aptos-vm/src/transaction_metadata.rs

View check run for this annotation

Codecov / codecov/patch

aptos-move/aptos-vm/src/transaction_metadata.rs#L108-L118

Added lines #L108 - L118 were not covered by tests
},
_ => txn.raw_transaction_ref().hash().to_vec(),

Check warning on line 120 in aptos-move/aptos-vm/src/transaction_metadata.rs

View check run for this annotation

Codecov / codecov/patch

aptos-move/aptos-vm/src/transaction_metadata.rs#L120

Added line #L120 was not covered by tests
},
}
}

Expand Down Expand Up @@ -158,6 +188,10 @@ impl TransactionMetadata {
self.multisig_payload.clone()
}

pub fn raw_transaction_hash(&self) -> Vec<u8> {
self.raw_transaction_hash.clone()
}

Check warning on line 193 in aptos-move/aptos-vm/src/transaction_metadata.rs

View check run for this annotation

Codecov / codecov/patch

aptos-move/aptos-vm/src/transaction_metadata.rs#L191-L193

Added lines #L191 - L193 were not covered by tests

pub fn as_user_transaction_context(&self) -> UserTransactionContext {
UserTransactionContext::new(
self.sender,
Expand All @@ -170,6 +204,7 @@ impl TransactionMetadata {
.map(|entry_func| entry_func.as_entry_function_payload()),
self.multisig_payload()
.map(|multisig| multisig.as_multisig_payload()),
self.raw_transaction_hash(),

Check warning on line 207 in aptos-move/aptos-vm/src/transaction_metadata.rs

View check run for this annotation

Codecov / codecov/patch

aptos-move/aptos-vm/src/transaction_metadata.rs#L207

Added line #L207 was not covered by tests
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ module admin::transaction_context_test {
type_arg_names: vector<String>,
args: vector<vector<u8>>,
multisig_address: address,
raw_transaction_hash: vector<u8>,
}

/// Called when the module is first deployed at address `signer`, which is supposed to be @admin (= 0x1).
Expand All @@ -44,6 +45,7 @@ module admin::transaction_context_test {
args: vector[],
type_arg_names: vector[],
multisig_address: @0x0,
raw_transaction_hash: vector[],
}
);
}
Expand Down Expand Up @@ -141,4 +143,14 @@ module admin::transaction_context_test {

store.multisig_address = multisig_account;
}

entry fun store_raw_transaction_hash_from_native_txn_context(_s: &signer) acquires TransactionContextStore {
let store = borrow_global_mut<TransactionContextStore>(@admin);
store.raw_transaction_hash = transaction_context::raw_transaction_hash();
}

entry fun store_raw_transaction_hash_from_native_txn_context_multi(_s: &signer, _s2: &signer) acquires TransactionContextStore {
let store = borrow_global_mut<TransactionContextStore>(@admin);
store.raw_transaction_hash = transaction_context::raw_transaction_hash();
}
}
28 changes: 28 additions & 0 deletions aptos-move/e2e-move-tests/src/tests/transaction_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

use crate::{assert_success, tests::common, MoveHarness};
use aptos_crypto::hash::CryptoHash;
use aptos_language_e2e_tests::account::{Account, TransactionBuilder};
use aptos_types::{
move_utils::MemberId,
Expand Down Expand Up @@ -31,6 +32,7 @@ struct TransactionContextStore {
type_arg_names: Vec<String>,
args: Vec<Vec<u8>>,
multisig_address: AccountAddress,
raw_transaction_hash: Vec<u8>,
}

fn setup(harness: &mut MoveHarness) -> Account {
Expand Down Expand Up @@ -468,3 +470,29 @@ fn test_transaction_context_multisig_payload() {
assert!(txn_ctx_store.type_arg_names.is_empty());
assert!(txn_ctx_store.args.is_empty());
}

#[test]
fn test_transaction_context_raw_transaction_hash() {
let mut harness = new_move_harness();
let account = setup(&mut harness);
let signed_txn = harness.create_entry_function(
&account,
str::parse(
"0x1::transaction_context_test::store_raw_transaction_hash_from_native_txn_context",
)
.unwrap(),
vec![],
vec![],
);
let expected_hash = signed_txn.clone().into_raw_transaction().hash();
let status = harness.run(signed_txn);
assert!(status.status().unwrap().is_success());
let txn_ctx_store = harness
.read_resource::<crate::tests::transaction_context::TransactionContextStore>(
account.address(),
parse_struct_tag("0x1::transaction_context_test::TransactionContextStore").unwrap(),
)
.unwrap();
let hash = txn_ctx_store.raw_transaction_hash;
assert_eq!(hash, expected_hash.to_vec());
}
103 changes: 76 additions & 27 deletions aptos-move/framework/aptos-framework/doc/transaction_context.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
- [Struct `EntryFunctionPayload`](#0x1_transaction_context_EntryFunctionPayload)
- [Struct `MultisigPayload`](#0x1_transaction_context_MultisigPayload)
- [Constants](#@Constants_0)
- [Function `get_txn_hash`](#0x1_transaction_context_get_txn_hash)
- [Function `get_transaction_hash`](#0x1_transaction_context_get_transaction_hash)
- [Function `get_txn_hash`](#0x1_transaction_context_get_txn_hash)
- [Function `generate_unique_address`](#0x1_transaction_context_generate_unique_address)
- [Function `generate_auid_address`](#0x1_transaction_context_generate_auid_address)
- [Function `get_script_hash`](#0x1_transaction_context_get_script_hash)
Expand Down Expand Up @@ -39,9 +39,11 @@
- [Function `multisig_payload_internal`](#0x1_transaction_context_multisig_payload_internal)
- [Function `multisig_address`](#0x1_transaction_context_multisig_address)
- [Function `inner_entry_function_payload`](#0x1_transaction_context_inner_entry_function_payload)
- [Function `raw_transaction_hash`](#0x1_transaction_context_raw_transaction_hash)
- [Function `raw_transaction_hash_internal`](#0x1_transaction_context_raw_transaction_hash_internal)
- [Specification](#@Specification_1)
- [Function `get_txn_hash`](#@Specification_1_get_txn_hash)
- [Function `get_transaction_hash`](#@Specification_1_get_transaction_hash)
- [Function `get_txn_hash`](#@Specification_1_get_txn_hash)
- [Function `generate_unique_address`](#@Specification_1_generate_unique_address)
- [Function `generate_auid_address`](#@Specification_1_generate_auid_address)
- [Function `get_script_hash`](#@Specification_1_get_script_hash)
Expand Down Expand Up @@ -206,14 +208,16 @@ Transaction context is only available in the user transaction prologue, executio



<a id="0x1_transaction_context_get_txn_hash"></a>
<a id="0x1_transaction_context_get_transaction_hash"></a>

## Function `get_txn_hash`
## Function `get_transaction_hash`

Returns the transaction hash of the current transaction.
Returns the hash of the internal session ID, providing a unique value for each transaction session
(prologue, execution, epilogue). Note that this is not the raw transaction hash used for authentication.
This function is created for to feature gate the <code>get_txn_hash</code> function.


<pre><code><b>fun</b> <a href="transaction_context.md#0x1_transaction_context_get_txn_hash">get_txn_hash</a>(): <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u8&gt;
<pre><code><b>public</b> <b>fun</b> <a href="transaction_context.md#0x1_transaction_context_get_transaction_hash">get_transaction_hash</a>(): <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u8&gt;
</code></pre>


Expand All @@ -222,23 +226,22 @@ Returns the transaction hash of the current transaction.
<summary>Implementation</summary>


<pre><code><b>native</b> <b>fun</b> <a href="transaction_context.md#0x1_transaction_context_get_txn_hash">get_txn_hash</a>(): <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u8&gt;;
<pre><code><b>public</b> <b>fun</b> <a href="transaction_context.md#0x1_transaction_context_get_transaction_hash">get_transaction_hash</a>(): <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u8&gt; {
<a href="transaction_context.md#0x1_transaction_context_get_txn_hash">get_txn_hash</a>()
}
</code></pre>



</details>

<a id="0x1_transaction_context_get_transaction_hash"></a>
<a id="0x1_transaction_context_get_txn_hash"></a>

## Function `get_transaction_hash`
## Function `get_txn_hash`

Returns the transaction hash of the current transaction.
Internally calls the private function <code>get_txn_hash</code>.
This function is created for to feature gate the <code>get_txn_hash</code> function.


<pre><code><b>public</b> <b>fun</b> <a href="transaction_context.md#0x1_transaction_context_get_transaction_hash">get_transaction_hash</a>(): <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u8&gt;
<pre><code><b>fun</b> <a href="transaction_context.md#0x1_transaction_context_get_txn_hash">get_txn_hash</a>(): <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u8&gt;
</code></pre>


Expand All @@ -247,9 +250,7 @@ This function is created for to feature gate the <code>get_txn_hash</code> funct
<summary>Implementation</summary>


<pre><code><b>public</b> <b>fun</b> <a href="transaction_context.md#0x1_transaction_context_get_transaction_hash">get_transaction_hash</a>(): <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u8&gt; {
<a href="transaction_context.md#0x1_transaction_context_get_txn_hash">get_txn_hash</a>()
}
<pre><code><b>native</b> <b>fun</b> <a href="transaction_context.md#0x1_transaction_context_get_txn_hash">get_txn_hash</a>(): <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u8&gt;;
</code></pre>


Expand Down Expand Up @@ -965,38 +966,59 @@ Returns the inner entry function payload of the multisig payload.

</details>

<a id="@Specification_1"></a>
<a id="0x1_transaction_context_raw_transaction_hash"></a>

## Specification
## Function `raw_transaction_hash`

Returns the hash of the current raw transaction, which is used for transaction authentication.
This function calls an internal native function to retrieve the raw transaction hash.

<a id="@Specification_1_get_txn_hash"></a>

### Function `get_txn_hash`
<pre><code><b>public</b> <b>fun</b> <a href="transaction_context.md#0x1_transaction_context_raw_transaction_hash">raw_transaction_hash</a>(): <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u8&gt;
</code></pre>


<pre><code><b>fun</b> <a href="transaction_context.md#0x1_transaction_context_get_txn_hash">get_txn_hash</a>(): <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u8&gt;

<details>
<summary>Implementation</summary>


<pre><code><b>public</b> <b>fun</b> <a href="transaction_context.md#0x1_transaction_context_raw_transaction_hash">raw_transaction_hash</a>(): <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u8&gt; {
<a href="transaction_context.md#0x1_transaction_context_raw_transaction_hash_internal">raw_transaction_hash_internal</a>()
}
</code></pre>



</details>

<pre><code><b>pragma</b> opaque;
<b>aborts_if</b> [abstract] <b>false</b>;
<b>ensures</b> result == <a href="transaction_context.md#0x1_transaction_context_spec_get_txn_hash">spec_get_txn_hash</a>();
</code></pre>
<a id="0x1_transaction_context_raw_transaction_hash_internal"></a>

## Function `raw_transaction_hash_internal`



<a id="0x1_transaction_context_spec_get_txn_hash"></a>
<pre><code><b>fun</b> <a href="transaction_context.md#0x1_transaction_context_raw_transaction_hash_internal">raw_transaction_hash_internal</a>(): <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u8&gt;
</code></pre>


<pre><code><b>fun</b> <a href="transaction_context.md#0x1_transaction_context_spec_get_txn_hash">spec_get_txn_hash</a>(): <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u8&gt;;

<details>
<summary>Implementation</summary>


<pre><code><b>native</b> <b>fun</b> <a href="transaction_context.md#0x1_transaction_context_raw_transaction_hash_internal">raw_transaction_hash_internal</a>(): <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u8&gt;;
</code></pre>



</details>

<a id="@Specification_1"></a>

## Specification


<a id="@Specification_1_get_transaction_hash"></a>

### Function `get_transaction_hash`
Expand All @@ -1017,6 +1039,33 @@ Returns the inner entry function payload of the multisig payload.



<a id="@Specification_1_get_txn_hash"></a>

### Function `get_txn_hash`


<pre><code><b>fun</b> <a href="transaction_context.md#0x1_transaction_context_get_txn_hash">get_txn_hash</a>(): <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u8&gt;
</code></pre>




<pre><code><b>pragma</b> opaque;
<b>aborts_if</b> [abstract] <b>false</b>;
<b>ensures</b> result == <a href="transaction_context.md#0x1_transaction_context_spec_get_txn_hash">spec_get_txn_hash</a>();
</code></pre>




<a id="0x1_transaction_context_spec_get_txn_hash"></a>


<pre><code><b>fun</b> <a href="transaction_context.md#0x1_transaction_context_spec_get_txn_hash">spec_get_txn_hash</a>(): <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u8&gt;;
</code></pre>



<a id="@Specification_1_generate_unique_address"></a>

### Function `generate_unique_address`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ module aptos_framework::transaction_context {
entry_function_payload: Option<EntryFunctionPayload>,
}

/// Returns the transaction hash of the current transaction.
native fun get_txn_hash(): vector<u8>;

/// Returns the transaction hash of the current transaction.
/// Internally calls the private function `get_txn_hash`.
/// Returns the hash of the internal session ID, providing a unique value for each transaction session
/// (prologue, execution, epilogue). Note that this is not the raw transaction hash used for authentication.
/// This function is created for to feature gate the `get_txn_hash` function.
public fun get_transaction_hash(): vector<u8> {
get_txn_hash()
}
native fun get_txn_hash(): vector<u8>;


/// Returns a universally unique identifier (of type address) generated
/// by hashing the transaction hash of this transaction and a sequence number
Expand Down Expand Up @@ -182,6 +182,13 @@ module aptos_framework::transaction_context {
payload.entry_function_payload
}

/// Returns the hash of the current raw transaction, which is used for transaction authentication.
/// This function calls an internal native function to retrieve the raw transaction hash.
public fun raw_transaction_hash(): vector<u8> {
raw_transaction_hash_internal()
}
native fun raw_transaction_hash_internal(): vector<u8>;

#[test()]
fun test_auid_uniquess() {
use std::vector;
Expand Down Expand Up @@ -259,4 +266,11 @@ module aptos_framework::transaction_context {
// expected to fail with the error code of `invalid_state(E_TRANSACTION_CONTEXT_NOT_AVAILABLE)`
let _multisig = multisig_payload();
}

#[test]
#[expected_failure(abort_code=196609, location = Self)]
fun test_call_raw_txn_hash() {
// expected to fail with the error code of `invalid_state(E_TRANSACTION_CONTEXT_NOT_AVAILABLE)`
let _multisig = multisig_payload();
}
}
Loading

0 comments on commit fa93aa3

Please sign in to comment.