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

Attached coinbase transaction to the owners table #836

Merged
merged 6 commits into from
Dec 14, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
82 changes: 63 additions & 19 deletions fuel-core/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use fuel_core_interfaces::{
fuel_storage,
fuel_tx::{
field::{
Inputs,
Outputs,
TxPointer as TxPointerField,
},
Expand Down Expand Up @@ -82,6 +83,7 @@ use fuel_core_interfaces::{
model::{
BlockId,
DaBlockHeight,
FuelBlock,
Message,
PartialFuelBlock,
PartialFuelBlockHeader,
Expand Down Expand Up @@ -246,13 +248,20 @@ impl Executor {
}
}

// ------------ GraphQL API Functionality BEGIN ------------

// save the status for every transaction using the finalized block id
self.persist_transaction_status(
finalized_block_id,
&mut tx_status,
block_db_transaction.deref_mut(),
)?;

// save the associated owner for each transaction in the block
self.index_tx_owners_for_block(&block, &mut block_db_transaction)?;

// ------------ GraphQL API Functionality END ------------

// insert block into database
block_db_transaction
.deref_mut()
Expand Down Expand Up @@ -443,9 +452,10 @@ impl Executor {
execution_data: &mut ExecutionData,
block_db_transaction: &mut DatabaseTransaction,
) -> Result<(), Error> {
let block_height = *block.header.height();
let coinbase_id = coinbase_tx.id();
self.persist_output_utxos(
*block.header.height(),
block_height,
&coinbase_id,
block_db_transaction,
&[],
Expand Down Expand Up @@ -513,7 +523,8 @@ impl Executor {

fn execute_create_or_script<Tx>(
&self,
idx: u16,
// TODO: Use it to calculate `TxPointer`.
_idx: u16,
original_tx: &mut Tx,
header: &PartialFuelBlockHeader,
execution_data: &mut ExecutionData,
Expand Down Expand Up @@ -562,15 +573,6 @@ impl Executor {
.map_err(TransactionValidityError::from)?;
}

// index owners of inputs and outputs with tx-id, regardless of validity (hence block_tx instead of tx_db)
self.persist_owners_index(
*header.height(),
checked_tx.transaction(),
&tx_id,
idx,
tx_db_transaction.deref_mut(),
)?;

// execute transaction
// setup database view that only lives for the duration of vm execution
let mut sub_block_db_commit = tx_db_transaction.transaction();
Expand Down Expand Up @@ -1228,28 +1230,62 @@ impl Executor {
Ok(())
}

/// Associate all transactions within a block to their respective UTXO owners
fn index_tx_owners_for_block(
&self,
block: &FuelBlock,
block_db_transaction: &mut DatabaseTransaction,
) -> Result<(), Error> {
for (tx_idx, tx) in block.transactions().iter().enumerate() {
let block_height = *block.header().height();
let mut inputs = &[][..];
let outputs;
let tx_id = tx.id();
match tx {
Transaction::Script(tx) => {
inputs = tx.inputs().as_slice();
outputs = tx.outputs().as_slice();
}
Transaction::Create(tx) => {
inputs = tx.inputs().as_slice();
outputs = tx.outputs().as_slice();
}
Transaction::Mint(tx) => {
outputs = tx.outputs().as_slice();
}
}
self.persist_owners_index(
block_height,
inputs,
outputs,
&tx_id,
tx_idx as u16,
block_db_transaction.deref_mut(),
)?;
}
Ok(())
}

/// Index the tx id by owner for all of the inputs and outputs
fn persist_owners_index<Tx>(
fn persist_owners_index(
&self,
block_height: BlockHeight,
tx: &Tx,
inputs: &[Input],
outputs: &[Output],
tx_id: &Bytes32,
tx_idx: u16,
db: &mut Database,
) -> Result<(), Error>
where
Tx: ExecutableTransaction,
{
) -> Result<(), Error> {
let mut owners = vec![];
for input in tx.inputs() {
for input in inputs {
if let Input::CoinSigned { owner, .. } | Input::CoinPredicate { owner, .. } =
input
{
owners.push(owner);
}
}

for output in tx.outputs() {
for output in outputs {
match output {
Output::Coin { to, .. }
| Output::Message { recipient: to, .. }
Expand Down Expand Up @@ -1715,6 +1751,14 @@ mod tests {
.execute_and_commit(ExecutionBlock::Validation(produced_block))
.unwrap();
assert_eq!(validated_block.transactions(), produced_txs);
let (_, owned_transactions_td_id) = validator
.database
.owned_transactions(&recipient, None, None)
.next()
.unwrap()
.unwrap();
// Should own `Mint` transaction
assert_eq!(owned_transactions_td_id, produced_txs[0].id());
}

#[test]
Expand Down
12 changes: 6 additions & 6 deletions fuel-tests/tests/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,9 @@ async fn get_transparent_transaction_by_id() {

#[tokio::test]
async fn get_transactions() {
let alice = Address::from([0; 32]);
let bob = Address::from([1; 32]);
let charlie = Address::from([2; 32]);
let alice = Address::from([1; 32]);
let bob = Address::from([2; 32]);
let charlie = Address::from([3; 32]);

let mut context = TestContext::new(100).await;
let tx1 = context.transfer(alice, charlie, 1).await.unwrap();
Expand Down Expand Up @@ -496,9 +496,9 @@ async fn get_transactions_from_manual_blocks() {

#[tokio::test]
async fn get_owned_transactions() {
let alice = Address::from([0; 32]);
let bob = Address::from([1; 32]);
let charlie = Address::from([2; 32]);
let alice = Address::from([1; 32]);
let bob = Address::from([2; 32]);
let charlie = Address::from([3; 32]);

let mut context = TestContext::new(100).await;
let tx1 = context.transfer(alice, charlie, 1).await.unwrap();
Expand Down