1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of Tetsy Vapory.

// Tetsy Vapory is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Tetsy Vapory is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Tetsy Vapory.  If not, see <http://www.gnu.org/licenses/>.

//! Tracing

use vapory_types::{U256, Address};
use tetsy_kvdb::DBTransaction;
use tetsy_vm::{Error as VmError, ActionParams};
// The MallocSizeOf derive looks for this in the root
use tetsy_util_mem as malloc_size_of;

mod config;
mod db;
mod executive_tracer;
mod import;
mod noop_tracer;
mod types;

pub use crate::{
	config::Config,
	db::{TraceDB, DatabaseExtras},
	localized::LocalizedTrace,
	executive_tracer::{ExecutiveTracer, ExecutiveVMTracer},
	import::ImportRequest,
	noop_tracer::{NoopTracer, NoopVMTracer},
	types::{
		Tracing,
		error::Error as TraceError,
		localized,
		trace::{self, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, RewardType},
		flat::{self, FlatTrace, FlatTransactionTraces, FlatBlockTraces},
		filter::{self, Filter, AddressesFilter},
	}
};

/// Type for block number.
pub(crate) type BlockNumber = u64;

/// This trait is used by executive to build traces.
pub trait Tracer: Send {
	/// Data returned when draining the Tracer.
	type Output;

	/// Prepares call trace for given params. Would panic if prepare/done_trace are not balanced.
	fn prepare_trace_call(&mut self, params: &ActionParams, depth: usize, is_builtin: bool);

	/// Prepares create trace for given params. Would panic if prepare/done_trace are not balanced.
	fn prepare_trace_create(&mut self, params: &ActionParams);

	/// Finishes a successful call trace. Would panic if prepare/done_trace are not balanced.
	fn done_trace_call(&mut self, gas_used: U256, output: &[u8]);

	/// Finishes a successful create trace. Would panic if prepare/done_trace are not balanced.
	fn done_trace_create(&mut self, gas_used: U256, code: &[u8], address: Address);

	/// Finishes a failed trace. Would panic if prepare/done_trace are not balanced.
	fn done_trace_failed(&mut self, error: &VmError);

	/// Stores suicide info.
	fn trace_suicide(&mut self, address: Address, balance: U256, refund_address: Address);

	/// Stores reward info.
	fn trace_reward(&mut self, author: Address, value: U256, reward_type: RewardType);

	/// Consumes self and returns all traces.
	fn drain(self) -> Vec<Self::Output>;
}

/// Used by executive to build VM traces.
pub trait VMTracer: Send {

	/// Data returned when draining the VMTracer.
	type Output;

	/// Trace the progression of interpreter to next instruction.
	/// If tracer returns `false` it won't be called again.
	/// @returns true if `trace_prepare_execute` and `trace_executed` should be called.
	fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8, _current_gas: U256) -> bool { false }

	/// Trace the preparation to execute a single valid instruction.
	fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _gas_cost: U256, _mem_written: Option<(usize, usize)>, _store_written: Option<(U256, U256)>) {}

	/// Trace the execution failure of a single instruction.
	fn trace_failed(&mut self) {}

	/// Trace the finalised execution of a single valid instruction.
	fn trace_executed(&mut self, _gas_used: U256, _stack_push: &[U256], _mem: &[u8]) {}

	/// Spawn subtracer which will be used to trace deeper levels of execution.
	fn prepare_subtrace(&mut self, _code: &[u8]) {}

	/// Finalize subtracer.
	fn done_subtrace(&mut self) {}

	/// Consumes self and returns the VM trace.
	fn drain(self) -> Option<Self::Output>;

}

/// Db provides an interface to query tracesdb.
pub trait Database {
	/// Returns true if tracing is enabled. Otherwise false.
	fn tracing_enabled(&self) -> bool;

	/// Imports new block traces.
	fn import(&self, batch: &mut DBTransaction, request: ImportRequest);

	/// Returns localized trace at given position.
	fn trace(&self, block_number: BlockNumber, tx_position: usize, trace_position: Vec<usize>) -> Option<LocalizedTrace>;

	/// Returns localized traces created by a single transaction.
	fn transaction_traces(&self, block_number: BlockNumber, tx_position: usize) -> Option<Vec<LocalizedTrace>>;

	/// Returns localized traces created in given block.
	fn block_traces(&self, block_number: BlockNumber) -> Option<Vec<LocalizedTrace>>;

	/// Filter traces matching given filter.
	fn filter(&self, filter: &Filter) -> Vec<LocalizedTrace>;
}