Beta Backports (#4012)
* Fix up the transaction JSON serialisation for RPC. * Introduce to_hex() utility in bigint. Fix tests. Conflicts: rpc/src/v1/tests/mocked/eth.rs rpc/src/v1/tests/mocked/signing.rs rpc/src/v1/types/block.rs rpc/src/v1/types/transaction.rs * fix comment * Fix build. * Bump hyper * Correct log index in transaction receipt (#3995) * Moving logs to separate, testable function * Adding test * Fixing log index * Adding transaction log index * Fixing rpc tests * Making interface of a bit cleaner. Conflicts: ethcore/src/client/client.rs ethcore/src/tests/client.rs ethcore/src/types/transaction.rs * Encode networkid as a u64. Conflicts: ethcore/src/types/transaction.rs * Fixing compilation issues * parse testnet chain as ropsten * Removing unused import Former-commit-id: 6782819dcfddf1858a32e88db007f2d0a8a00092
This commit is contained in:
parent
84021a6148
commit
da5b506603
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -737,7 +737,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
source = "git+https://github.com/ethcore/hyper#9e346c1d4bc30cd4142dea9d8a0b117d30858ca4"
|
source = "git+https://github.com/ethcore/hyper#4379a3629abc10e42e6d3fbcb21ecef5c1c86a77"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -140,7 +140,7 @@ pub trait BlockProvider {
|
|||||||
fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockNumber, to_block: BlockNumber) -> Vec<BlockNumber>;
|
fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockNumber, to_block: BlockNumber) -> Vec<BlockNumber>;
|
||||||
|
|
||||||
/// Returns logs matching given filter.
|
/// Returns logs matching given filter.
|
||||||
fn logs<F>(&self, mut blocks: Vec<BlockNumber>, matches: F, limit: Option<usize>) -> Vec<LocalizedLogEntry>
|
fn logs<F>(&self, blocks: Vec<BlockNumber>, matches: F, limit: Option<usize>) -> Vec<LocalizedLogEntry>
|
||||||
where F: Fn(&LogEntry) -> bool, Self: Sized;
|
where F: Fn(&LogEntry) -> bool, Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,7 +371,8 @@ impl BlockProvider for BlockChain {
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
.flat_map(move |(index, (mut logs, tx_hash))| {
|
.flat_map(move |(index, (mut logs, tx_hash))| {
|
||||||
let current_log_index = log_index;
|
let current_log_index = log_index;
|
||||||
log_index -= logs.len();
|
let no_of_logs = logs.len();
|
||||||
|
log_index -= no_of_logs;
|
||||||
|
|
||||||
logs.reverse();
|
logs.reverse();
|
||||||
logs.into_iter()
|
logs.into_iter()
|
||||||
@ -383,6 +384,7 @@ impl BlockProvider for BlockChain {
|
|||||||
transaction_hash: tx_hash,
|
transaction_hash: tx_hash,
|
||||||
// iterating in reverse order
|
// iterating in reverse order
|
||||||
transaction_index: receipts_len - index - 1,
|
transaction_index: receipts_len - index - 1,
|
||||||
|
transaction_log_index: no_of_logs - i - 1,
|
||||||
log_index: current_log_index - i - 1,
|
log_index: current_log_index - i - 1,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -1924,6 +1926,7 @@ mod tests {
|
|||||||
block_number: block1.header().number(),
|
block_number: block1.header().number(),
|
||||||
transaction_hash: tx_hash1.clone(),
|
transaction_hash: tx_hash1.clone(),
|
||||||
transaction_index: 0,
|
transaction_index: 0,
|
||||||
|
transaction_log_index: 0,
|
||||||
log_index: 0,
|
log_index: 0,
|
||||||
},
|
},
|
||||||
LocalizedLogEntry {
|
LocalizedLogEntry {
|
||||||
@ -1932,6 +1935,7 @@ mod tests {
|
|||||||
block_number: block1.header().number(),
|
block_number: block1.header().number(),
|
||||||
transaction_hash: tx_hash1.clone(),
|
transaction_hash: tx_hash1.clone(),
|
||||||
transaction_index: 0,
|
transaction_index: 0,
|
||||||
|
transaction_log_index: 1,
|
||||||
log_index: 1,
|
log_index: 1,
|
||||||
},
|
},
|
||||||
LocalizedLogEntry {
|
LocalizedLogEntry {
|
||||||
@ -1940,6 +1944,7 @@ mod tests {
|
|||||||
block_number: block1.header().number(),
|
block_number: block1.header().number(),
|
||||||
transaction_hash: tx_hash2.clone(),
|
transaction_hash: tx_hash2.clone(),
|
||||||
transaction_index: 1,
|
transaction_index: 1,
|
||||||
|
transaction_log_index: 0,
|
||||||
log_index: 2,
|
log_index: 2,
|
||||||
},
|
},
|
||||||
LocalizedLogEntry {
|
LocalizedLogEntry {
|
||||||
@ -1948,6 +1953,7 @@ mod tests {
|
|||||||
block_number: block2.header().number(),
|
block_number: block2.header().number(),
|
||||||
transaction_hash: tx_hash3.clone(),
|
transaction_hash: tx_hash3.clone(),
|
||||||
transaction_index: 0,
|
transaction_index: 0,
|
||||||
|
transaction_log_index: 0,
|
||||||
log_index: 0,
|
log_index: 0,
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
@ -1958,6 +1964,7 @@ mod tests {
|
|||||||
block_number: block2.header().number(),
|
block_number: block2.header().number(),
|
||||||
transaction_hash: tx_hash3.clone(),
|
transaction_hash: tx_hash3.clone(),
|
||||||
transaction_index: 0,
|
transaction_index: 0,
|
||||||
|
transaction_log_index: 0,
|
||||||
log_index: 0,
|
log_index: 0,
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
@ -58,7 +58,7 @@ use client::{
|
|||||||
use client::Error as ClientError;
|
use client::Error as ClientError;
|
||||||
use env_info::EnvInfo;
|
use env_info::EnvInfo;
|
||||||
use executive::{Executive, Executed, TransactOptions, contract_address};
|
use executive::{Executive, Executed, TransactOptions, contract_address};
|
||||||
use receipt::LocalizedReceipt;
|
use receipt::{Receipt, LocalizedReceipt};
|
||||||
use trace::{TraceDB, ImportRequest as TraceImportRequest, LocalizedTrace, Database as TraceDatabase};
|
use trace::{TraceDB, ImportRequest as TraceImportRequest, LocalizedTrace, Database as TraceDatabase};
|
||||||
use trace;
|
use trace;
|
||||||
use trace::FlatTransactionTraces;
|
use trace::FlatTransactionTraces;
|
||||||
@ -787,7 +787,6 @@ impl snapshot::DatabaseRestore for Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl BlockChainClient for Client {
|
impl BlockChainClient for Client {
|
||||||
fn call(&self, t: &SignedTransaction, block: BlockID, analytics: CallAnalytics) -> Result<Executed, CallError> {
|
fn call(&self, t: &SignedTransaction, block: BlockID, analytics: CallAnalytics) -> Result<Executed, CallError> {
|
||||||
let header = try!(self.block_header(block).ok_or(CallError::StatePruned));
|
let header = try!(self.block_header(block).ok_or(CallError::StatePruned));
|
||||||
@ -1012,53 +1011,23 @@ impl BlockChainClient for Client {
|
|||||||
let chain = self.chain.read();
|
let chain = self.chain.read();
|
||||||
self.transaction_address(id)
|
self.transaction_address(id)
|
||||||
.and_then(|address| chain.block_number(&address.block_hash).and_then(|block_number| {
|
.and_then(|address| chain.block_number(&address.block_hash).and_then(|block_number| {
|
||||||
let t = chain.block_body(&address.block_hash)
|
let transaction = chain.block_body(&address.block_hash)
|
||||||
.and_then(|block| {
|
.and_then(|body| BodyView::new(&body).localized_transaction_at(&address.block_hash, block_number, address.index));
|
||||||
BodyView::new(&block).localized_transaction_at(&address.block_hash, block_number, address.index)
|
|
||||||
});
|
|
||||||
|
|
||||||
let tx_and_sender = t.and_then(|tx| tx.sender().ok().map(|sender| (tx, sender)));
|
let previous_receipts = (0..address.index + 1)
|
||||||
|
.map(|index| {
|
||||||
match (tx_and_sender, chain.transaction_receipt(&address)) {
|
let mut address = address.clone();
|
||||||
(Some((tx, sender)), Some(receipt)) => {
|
address.index = index;
|
||||||
let block_hash = tx.block_hash.clone();
|
chain.transaction_receipt(&address)
|
||||||
let block_number = tx.block_number.clone();
|
|
||||||
let transaction_hash = tx.hash();
|
|
||||||
let transaction_index = tx.transaction_index;
|
|
||||||
let prior_gas_used = match tx.transaction_index {
|
|
||||||
0 => U256::zero(),
|
|
||||||
i => {
|
|
||||||
let prior_address = TransactionAddress { block_hash: address.block_hash, index: i - 1 };
|
|
||||||
let prior_receipt = chain.transaction_receipt(&prior_address).expect("Transaction receipt at `address` exists; `prior_address` has lower index in same block; qed");
|
|
||||||
prior_receipt.gas_used
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Some(LocalizedReceipt {
|
|
||||||
transaction_hash: tx.hash(),
|
|
||||||
transaction_index: tx.transaction_index,
|
|
||||||
block_hash: tx.block_hash,
|
|
||||||
block_number: tx.block_number,
|
|
||||||
cumulative_gas_used: receipt.gas_used,
|
|
||||||
gas_used: receipt.gas_used - prior_gas_used,
|
|
||||||
contract_address: match tx.action {
|
|
||||||
Action::Call(_) => None,
|
|
||||||
Action::Create => Some(contract_address(&sender, &tx.nonce))
|
|
||||||
},
|
|
||||||
logs: receipt.logs.into_iter().enumerate().map(|(i, log)| LocalizedLogEntry {
|
|
||||||
entry: log,
|
|
||||||
block_hash: block_hash.clone(),
|
|
||||||
block_number: block_number,
|
|
||||||
transaction_hash: transaction_hash.clone(),
|
|
||||||
transaction_index: transaction_index,
|
|
||||||
log_index: i
|
|
||||||
}).collect(),
|
|
||||||
log_bloom: receipt.log_bloom,
|
|
||||||
state_root: receipt.state_root,
|
|
||||||
})
|
})
|
||||||
},
|
.collect();
|
||||||
_ => None
|
match (transaction, previous_receipts) {
|
||||||
}
|
(Some(transaction), Some(previous_receipts)) => {
|
||||||
}))
|
Some(transaction_receipt(transaction, previous_receipts))
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tree_route(&self, from: &H256, to: &H256) -> Option<TreeRoute> {
|
fn tree_route(&self, from: &H256, to: &H256) -> Option<TreeRoute> {
|
||||||
@ -1215,7 +1184,7 @@ impl BlockChainClient for Client {
|
|||||||
self.miner.pending_transactions(self.chain.read().best_block_number())
|
self.miner.pending_transactions(self.chain.read().best_block_number())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signing_network_id(&self) -> Option<u8> {
|
fn signing_network_id(&self) -> Option<u64> {
|
||||||
self.engine.signing_network_id(&self.latest_env_info())
|
self.engine.signing_network_id(&self.latest_env_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1319,32 +1288,169 @@ impl MayPanic for Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `LocalizedReceipt` given `LocalizedTransaction`
|
||||||
|
/// and a vector of receipts from given block up to transaction index.
|
||||||
|
fn transaction_receipt(tx: LocalizedTransaction, mut receipts: Vec<Receipt>) -> LocalizedReceipt {
|
||||||
|
assert_eq!(receipts.len(), tx.transaction_index + 1, "All previous receipts are provided.");
|
||||||
|
|
||||||
#[test]
|
let sender = tx.sender()
|
||||||
fn should_not_cache_details_before_commit() {
|
.expect("LocalizedTransaction is part of the blockchain; We have only valid transactions in chain; qed");
|
||||||
use tests::helpers::*;
|
let receipt = receipts.pop().expect("Current receipt is provided; qed");
|
||||||
use std::thread;
|
let prior_gas_used = match tx.transaction_index {
|
||||||
use std::time::Duration;
|
0 => 0.into(),
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
i => receipts.get(i - 1).expect("All previous receipts are provided; qed").gas_used,
|
||||||
|
|
||||||
let client = generate_dummy_client(0);
|
|
||||||
let genesis = client.chain_info().best_block_hash;
|
|
||||||
let (new_hash, new_block) = get_good_dummy_block_hash();
|
|
||||||
|
|
||||||
let go = {
|
|
||||||
// Separate thread uncommited transaction
|
|
||||||
let go = Arc::new(AtomicBool::new(false));
|
|
||||||
let go_thread = go.clone();
|
|
||||||
let another_client = client.reference().clone();
|
|
||||||
thread::spawn(move || {
|
|
||||||
let mut batch = DBTransaction::new(&*another_client.chain.read().db().clone());
|
|
||||||
another_client.chain.read().insert_block(&mut batch, &new_block, Vec::new());
|
|
||||||
go_thread.store(true, Ordering::SeqCst);
|
|
||||||
});
|
|
||||||
go
|
|
||||||
};
|
};
|
||||||
|
let no_of_logs = receipts.into_iter().map(|receipt| receipt.logs.len()).sum::<usize>();
|
||||||
|
let transaction_hash = tx.hash();
|
||||||
|
let block_hash = tx.block_hash;
|
||||||
|
let block_number = tx.block_number;
|
||||||
|
let transaction_index = tx.transaction_index;
|
||||||
|
|
||||||
while !go.load(Ordering::SeqCst) { thread::park_timeout(Duration::from_millis(5)); }
|
LocalizedReceipt {
|
||||||
|
transaction_hash: transaction_hash,
|
||||||
assert!(client.tree_route(&genesis, &new_hash).is_none());
|
transaction_index: transaction_index,
|
||||||
|
block_hash: block_hash,
|
||||||
|
block_number:block_number,
|
||||||
|
cumulative_gas_used: receipt.gas_used,
|
||||||
|
gas_used: receipt.gas_used - prior_gas_used,
|
||||||
|
contract_address: match tx.action {
|
||||||
|
Action::Call(_) => None,
|
||||||
|
Action::Create => Some(contract_address(&sender, &tx.nonce))
|
||||||
|
},
|
||||||
|
logs: receipt.logs.into_iter().enumerate().map(|(i, log)| LocalizedLogEntry {
|
||||||
|
entry: log,
|
||||||
|
block_hash: block_hash,
|
||||||
|
block_number: block_number,
|
||||||
|
transaction_hash: transaction_hash,
|
||||||
|
transaction_index: transaction_index,
|
||||||
|
transaction_log_index: i,
|
||||||
|
log_index: no_of_logs + i,
|
||||||
|
}).collect(),
|
||||||
|
log_bloom: receipt.log_bloom,
|
||||||
|
state_root: receipt.state_root,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_not_cache_details_before_commit() {
|
||||||
|
use client::BlockChainClient;
|
||||||
|
use tests::helpers::*;
|
||||||
|
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use util::kvdb::DBTransaction;
|
||||||
|
|
||||||
|
let client = generate_dummy_client(0);
|
||||||
|
let genesis = client.chain_info().best_block_hash;
|
||||||
|
let (new_hash, new_block) = get_good_dummy_block_hash();
|
||||||
|
|
||||||
|
let go = {
|
||||||
|
// Separate thread uncommited transaction
|
||||||
|
let go = Arc::new(AtomicBool::new(false));
|
||||||
|
let go_thread = go.clone();
|
||||||
|
let another_client = client.reference().clone();
|
||||||
|
thread::spawn(move || {
|
||||||
|
let mut batch = DBTransaction::new(&*another_client.chain.read().db().clone());
|
||||||
|
another_client.chain.read().insert_block(&mut batch, &new_block, Vec::new());
|
||||||
|
go_thread.store(true, Ordering::SeqCst);
|
||||||
|
});
|
||||||
|
go
|
||||||
|
};
|
||||||
|
|
||||||
|
while !go.load(Ordering::SeqCst) { thread::park_timeout(Duration::from_millis(5)); }
|
||||||
|
|
||||||
|
assert!(client.tree_route(&genesis, &new_hash).is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_return_correct_log_index() {
|
||||||
|
use super::transaction_receipt;
|
||||||
|
use ethkey::KeyPair;
|
||||||
|
use log_entry::{LogEntry, LocalizedLogEntry};
|
||||||
|
use receipt::{Receipt, LocalizedReceipt};
|
||||||
|
use transaction::{Transaction, LocalizedTransaction, Action};
|
||||||
|
use util::Hashable;
|
||||||
|
|
||||||
|
// given
|
||||||
|
let key = KeyPair::from_secret("test".sha3()).unwrap();
|
||||||
|
let secret = key.secret();
|
||||||
|
|
||||||
|
let block_number = 1;
|
||||||
|
let block_hash = 5.into();
|
||||||
|
let state_root = 99.into();
|
||||||
|
let gas_used = 10.into();
|
||||||
|
let raw_tx = Transaction {
|
||||||
|
nonce: 0.into(),
|
||||||
|
gas_price: 0.into(),
|
||||||
|
gas: 21000.into(),
|
||||||
|
action: Action::Call(10.into()),
|
||||||
|
value: 0.into(),
|
||||||
|
data: vec![],
|
||||||
|
};
|
||||||
|
let tx1 = raw_tx.clone().sign(secret, None);
|
||||||
|
let transaction = LocalizedTransaction {
|
||||||
|
signed: tx1.clone(),
|
||||||
|
block_number: block_number,
|
||||||
|
block_hash: block_hash,
|
||||||
|
transaction_index: 1,
|
||||||
|
};
|
||||||
|
let logs = vec![LogEntry {
|
||||||
|
address: 5.into(),
|
||||||
|
topics: vec![],
|
||||||
|
data: vec![],
|
||||||
|
}, LogEntry {
|
||||||
|
address: 15.into(),
|
||||||
|
topics: vec![],
|
||||||
|
data: vec![],
|
||||||
|
}];
|
||||||
|
let receipts = vec![Receipt {
|
||||||
|
state_root: state_root,
|
||||||
|
gas_used: 5.into(),
|
||||||
|
log_bloom: Default::default(),
|
||||||
|
logs: vec![logs[0].clone()],
|
||||||
|
}, Receipt {
|
||||||
|
state_root: state_root,
|
||||||
|
gas_used: gas_used,
|
||||||
|
log_bloom: Default::default(),
|
||||||
|
logs: logs.clone(),
|
||||||
|
}];
|
||||||
|
|
||||||
|
// when
|
||||||
|
let receipt = transaction_receipt(transaction, receipts);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assert_eq!(receipt, LocalizedReceipt {
|
||||||
|
transaction_hash: tx1.hash(),
|
||||||
|
transaction_index: 1,
|
||||||
|
block_hash: block_hash,
|
||||||
|
block_number: block_number,
|
||||||
|
cumulative_gas_used: gas_used,
|
||||||
|
gas_used: gas_used - 5.into(),
|
||||||
|
contract_address: None,
|
||||||
|
logs: vec![LocalizedLogEntry {
|
||||||
|
entry: logs[0].clone(),
|
||||||
|
block_hash: block_hash,
|
||||||
|
block_number: block_number,
|
||||||
|
transaction_hash: tx1.hash(),
|
||||||
|
transaction_index: 1,
|
||||||
|
transaction_log_index: 0,
|
||||||
|
log_index: 1,
|
||||||
|
}, LocalizedLogEntry {
|
||||||
|
entry: logs[1].clone(),
|
||||||
|
block_hash: block_hash,
|
||||||
|
block_number: block_number,
|
||||||
|
transaction_hash: tx1.hash(),
|
||||||
|
transaction_index: 1,
|
||||||
|
transaction_log_index: 1,
|
||||||
|
log_index: 2,
|
||||||
|
}],
|
||||||
|
log_bloom: Default::default(),
|
||||||
|
state_root: state_root,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -654,7 +654,7 @@ impl BlockChainClient for TestBlockChainClient {
|
|||||||
self.miner.pending_transactions(self.chain_info().best_block_number)
|
self.miner.pending_transactions(self.chain_info().best_block_number)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signing_network_id(&self) -> Option<u8> { None }
|
fn signing_network_id(&self) -> Option<u64> { None }
|
||||||
|
|
||||||
fn mode(&self) -> Mode { Mode::Active }
|
fn mode(&self) -> Mode { Mode::Active }
|
||||||
|
|
||||||
|
@ -229,7 +229,7 @@ pub trait BlockChainClient : Sync + Send {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the preferred network ID to sign on
|
/// Get the preferred network ID to sign on
|
||||||
fn signing_network_id(&self) -> Option<u8>;
|
fn signing_network_id(&self) -> Option<u64>;
|
||||||
|
|
||||||
/// Get the mode.
|
/// Get the mode.
|
||||||
fn mode(&self) -> Mode;
|
fn mode(&self) -> Mode;
|
||||||
|
@ -109,7 +109,7 @@ pub trait Engine : Sync + Send {
|
|||||||
fn verify_transaction(&self, _t: &SignedTransaction, _header: &Header) -> Result<(), Error> { Ok(()) }
|
fn verify_transaction(&self, _t: &SignedTransaction, _header: &Header) -> Result<(), Error> { Ok(()) }
|
||||||
|
|
||||||
/// The network ID that transactions should be signed with.
|
/// The network ID that transactions should be signed with.
|
||||||
fn signing_network_id(&self, _env_info: &EnvInfo) -> Option<u8> { None }
|
fn signing_network_id(&self, _env_info: &EnvInfo) -> Option<u64> { None }
|
||||||
|
|
||||||
/// Verify the seal of a block. This is an auxilliary method that actually just calls other `verify_` methods
|
/// Verify the seal of a block. This is an auxilliary method that actually just calls other `verify_` methods
|
||||||
/// to get the job done. By default it must pass `verify_basic` and `verify_block_unordered`. If more or fewer
|
/// to get the job done. By default it must pass `verify_basic` and `verify_block_unordered`. If more or fewer
|
||||||
|
@ -157,9 +157,9 @@ impl Engine for Ethash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signing_network_id(&self, env_info: &EnvInfo) -> Option<u8> {
|
fn signing_network_id(&self, env_info: &EnvInfo) -> Option<u64> {
|
||||||
if env_info.number >= self.ethash_params.eip155_transition && self.params().network_id < 127 {
|
if env_info.number >= self.ethash_params.eip155_transition {
|
||||||
Some(self.params().network_id as u8)
|
Some(self.params().network_id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -308,7 +308,7 @@ impl Engine for Ethash {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(n) = t.network_id() {
|
if let Some(n) = t.network_id() {
|
||||||
if header.number() < self.ethash_params.eip155_transition || n as usize != self.params().network_id {
|
if header.number() < self.ethash_params.eip155_transition || n != self.params().network_id {
|
||||||
return Err(TransactionError::InvalidNetworkId.into())
|
return Err(TransactionError::InvalidNetworkId.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ pub struct CommonParams {
|
|||||||
/// Maximum size of extra data.
|
/// Maximum size of extra data.
|
||||||
pub maximum_extra_data_size: usize,
|
pub maximum_extra_data_size: usize,
|
||||||
/// Network id.
|
/// Network id.
|
||||||
pub network_id: usize,
|
pub network_id: u64,
|
||||||
/// Main subprotocol name.
|
/// Main subprotocol name.
|
||||||
pub subprotocol_name: String,
|
pub subprotocol_name: String,
|
||||||
/// Minimum gas limit.
|
/// Minimum gas limit.
|
||||||
@ -160,7 +160,7 @@ impl Spec {
|
|||||||
pub fn nodes(&self) -> &[String] { &self.nodes }
|
pub fn nodes(&self) -> &[String] { &self.nodes }
|
||||||
|
|
||||||
/// Get the configured Network ID.
|
/// Get the configured Network ID.
|
||||||
pub fn network_id(&self) -> usize { self.params.network_id }
|
pub fn network_id(&self) -> u64 { self.params.network_id }
|
||||||
|
|
||||||
/// Get the configured Network ID.
|
/// Get the configured Network ID.
|
||||||
pub fn subprotocol_name(&self) -> String { self.params.subprotocol_name.clone() }
|
pub fn subprotocol_name(&self) -> String { self.params.subprotocol_name.clone() }
|
||||||
|
@ -95,6 +95,8 @@ pub struct LocalizedLogEntry {
|
|||||||
pub transaction_index: usize,
|
pub transaction_index: usize,
|
||||||
/// Log position in the block.
|
/// Log position in the block.
|
||||||
pub log_index: usize,
|
pub log_index: usize,
|
||||||
|
/// Log position in the transaction.
|
||||||
|
pub transaction_log_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for LocalizedLogEntry {
|
impl Deref for LocalizedLogEntry {
|
||||||
|
@ -72,8 +72,8 @@ pub struct Transaction {
|
|||||||
|
|
||||||
impl Transaction {
|
impl Transaction {
|
||||||
/// Append object with a without signature into RLP stream
|
/// Append object with a without signature into RLP stream
|
||||||
pub fn rlp_append_unsigned_transaction(&self, s: &mut RlpStream, network_id: Option<u8>) {
|
pub fn rlp_append_unsigned_transaction(&self, s: &mut RlpStream, network_id: Option<u64>) {
|
||||||
s.begin_list(if let None = network_id { 6 } else { 9 });
|
s.begin_list(if network_id.is_none() { 6 } else { 9 });
|
||||||
s.append(&self.nonce);
|
s.append(&self.nonce);
|
||||||
s.append(&self.gas_price);
|
s.append(&self.gas_price);
|
||||||
s.append(&self.gas);
|
s.append(&self.gas);
|
||||||
@ -140,26 +140,26 @@ impl From<ethjson::transaction::Transaction> for SignedTransaction {
|
|||||||
|
|
||||||
impl Transaction {
|
impl Transaction {
|
||||||
/// The message hash of the transaction.
|
/// The message hash of the transaction.
|
||||||
pub fn hash(&self, network_id: Option<u8>) -> H256 {
|
pub fn hash(&self, network_id: Option<u64>) -> H256 {
|
||||||
let mut stream = RlpStream::new();
|
let mut stream = RlpStream::new();
|
||||||
self.rlp_append_unsigned_transaction(&mut stream, network_id);
|
self.rlp_append_unsigned_transaction(&mut stream, network_id);
|
||||||
stream.out().sha3()
|
stream.out().sha3()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signs the transaction as coming from `sender`.
|
/// Signs the transaction as coming from `sender`.
|
||||||
pub fn sign(self, secret: &Secret, network_id: Option<u8>) -> SignedTransaction {
|
pub fn sign(self, secret: &Secret, network_id: Option<u64>) -> SignedTransaction {
|
||||||
let sig = ::ethkey::sign(secret, &self.hash(network_id))
|
let sig = ::ethkey::sign(secret, &self.hash(network_id))
|
||||||
.expect("data is valid and context has signing capabilities; qed");
|
.expect("data is valid and context has signing capabilities; qed");
|
||||||
self.with_signature(sig, network_id)
|
self.with_signature(sig, network_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signs the transaction with signature.
|
/// Signs the transaction with signature.
|
||||||
pub fn with_signature(self, sig: Signature, network_id: Option<u8>) -> SignedTransaction {
|
pub fn with_signature(self, sig: Signature, network_id: Option<u64>) -> SignedTransaction {
|
||||||
SignedTransaction {
|
SignedTransaction {
|
||||||
unsigned: self,
|
unsigned: self,
|
||||||
r: sig.r().into(),
|
r: sig.r().into(),
|
||||||
s: sig.s().into(),
|
s: sig.s().into(),
|
||||||
v: sig.v() + if let Some(n) = network_id { 35 + n * 2 } else { 27 },
|
v: sig.v() as u64 + if let Some(n) = network_id { 35 + n * 2 } else { 27 },
|
||||||
hash: Cell::new(None),
|
hash: Cell::new(None),
|
||||||
sender: Cell::new(None),
|
sender: Cell::new(None),
|
||||||
}
|
}
|
||||||
@ -211,7 +211,7 @@ pub struct SignedTransaction {
|
|||||||
unsigned: Transaction,
|
unsigned: Transaction,
|
||||||
/// The V field of the signature; the LS bit described which half of the curve our point falls
|
/// The V field of the signature; the LS bit described which half of the curve our point falls
|
||||||
/// in. The MS bits describe which network this transaction is for. If 27/28, its for all networks.
|
/// in. The MS bits describe which network this transaction is for. If 27/28, its for all networks.
|
||||||
v: u8,
|
v: u64,
|
||||||
/// The R field of the signature; helps describe the point on the curve.
|
/// The R field of the signature; helps describe the point on the curve.
|
||||||
r: U256,
|
r: U256,
|
||||||
/// The S field of the signature; helps describe the point on the curve.
|
/// The S field of the signature; helps describe the point on the curve.
|
||||||
@ -302,10 +302,13 @@ impl SignedTransaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 0 if `v` would have been 27 under "Electrum" notation, 1 if 28 or 4 if invalid.
|
/// 0 if `v` would have been 27 under "Electrum" notation, 1 if 28 or 4 if invalid.
|
||||||
pub fn standard_v(&self) -> u8 { match self.v { v if v == 27 || v == 28 || v > 36 => (v - 1) % 2, _ => 4 } }
|
pub fn standard_v(&self) -> u8 { match self.v { v if v == 27 || v == 28 || v > 36 => ((v - 1) % 2) as u8, _ => 4 } }
|
||||||
|
|
||||||
|
/// The `v` value that appears in the RLP.
|
||||||
|
pub fn original_v(&self) -> u64 { self.v }
|
||||||
|
|
||||||
/// The network ID, or `None` if this is a global transaction.
|
/// The network ID, or `None` if this is a global transaction.
|
||||||
pub fn network_id(&self) -> Option<u8> {
|
pub fn network_id(&self) -> Option<u64> {
|
||||||
match self.v {
|
match self.v {
|
||||||
v if v > 36 => Some((v - 35) / 2),
|
v if v > 36 => Some((v - 35) / 2),
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -367,7 +370,7 @@ impl SignedTransaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Signed Transaction that is a part of canon blockchain.
|
/// Signed Transaction that is a part of canon blockchain.
|
||||||
#[derive(Debug, PartialEq, Eq, Binary)]
|
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
|
||||||
pub struct LocalizedTransaction {
|
pub struct LocalizedTransaction {
|
||||||
/// Signed part.
|
/// Signed part.
|
||||||
pub signed: SignedTransaction,
|
pub signed: SignedTransaction,
|
||||||
|
@ -27,7 +27,7 @@ use user_defaults::UserDefaults;
|
|||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum SpecType {
|
pub enum SpecType {
|
||||||
Mainnet,
|
Mainnet,
|
||||||
Testnet,
|
Morden,
|
||||||
Ropsten,
|
Ropsten,
|
||||||
Olympic,
|
Olympic,
|
||||||
Classic,
|
Classic,
|
||||||
@ -48,8 +48,8 @@ impl str::FromStr for SpecType {
|
|||||||
let spec = match s {
|
let spec = match s {
|
||||||
"frontier" | "homestead" | "mainnet" => SpecType::Mainnet,
|
"frontier" | "homestead" | "mainnet" => SpecType::Mainnet,
|
||||||
"frontier-dogmatic" | "homestead-dogmatic" | "classic" => SpecType::Classic,
|
"frontier-dogmatic" | "homestead-dogmatic" | "classic" => SpecType::Classic,
|
||||||
"morden" | "testnet" => SpecType::Testnet,
|
"morden" => SpecType::Morden,
|
||||||
"ropsten" => SpecType::Ropsten,
|
"ropsten" | "testnet" => SpecType::Ropsten,
|
||||||
"olympic" => SpecType::Olympic,
|
"olympic" => SpecType::Olympic,
|
||||||
"expanse" => SpecType::Expanse,
|
"expanse" => SpecType::Expanse,
|
||||||
other => SpecType::Custom(other.into()),
|
other => SpecType::Custom(other.into()),
|
||||||
@ -62,7 +62,7 @@ impl SpecType {
|
|||||||
pub fn spec(&self) -> Result<Spec, String> {
|
pub fn spec(&self) -> Result<Spec, String> {
|
||||||
match *self {
|
match *self {
|
||||||
SpecType::Mainnet => Ok(ethereum::new_frontier()),
|
SpecType::Mainnet => Ok(ethereum::new_frontier()),
|
||||||
SpecType::Testnet => Ok(ethereum::new_morden()),
|
SpecType::Morden => Ok(ethereum::new_morden()),
|
||||||
SpecType::Ropsten => Ok(ethereum::new_ropsten()),
|
SpecType::Ropsten => Ok(ethereum::new_ropsten()),
|
||||||
SpecType::Olympic => Ok(ethereum::new_olympic()),
|
SpecType::Olympic => Ok(ethereum::new_olympic()),
|
||||||
SpecType::Classic => Ok(ethereum::new_classic()),
|
SpecType::Classic => Ok(ethereum::new_classic()),
|
||||||
@ -283,10 +283,11 @@ mod tests {
|
|||||||
assert_eq!(SpecType::Mainnet, "frontier".parse().unwrap());
|
assert_eq!(SpecType::Mainnet, "frontier".parse().unwrap());
|
||||||
assert_eq!(SpecType::Mainnet, "homestead".parse().unwrap());
|
assert_eq!(SpecType::Mainnet, "homestead".parse().unwrap());
|
||||||
assert_eq!(SpecType::Mainnet, "mainnet".parse().unwrap());
|
assert_eq!(SpecType::Mainnet, "mainnet".parse().unwrap());
|
||||||
assert_eq!(SpecType::Testnet, "testnet".parse().unwrap());
|
assert_eq!(SpecType::Ropsten, "testnet".parse().unwrap());
|
||||||
assert_eq!(SpecType::Testnet, "morden".parse().unwrap());
|
assert_eq!(SpecType::Morden, "morden".parse().unwrap());
|
||||||
assert_eq!(SpecType::Ropsten, "ropsten".parse().unwrap());
|
assert_eq!(SpecType::Ropsten, "ropsten".parse().unwrap());
|
||||||
assert_eq!(SpecType::Olympic, "olympic".parse().unwrap());
|
assert_eq!(SpecType::Olympic, "olympic".parse().unwrap());
|
||||||
|
assert_eq!(SpecType::Classic, "classic".parse().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -177,7 +177,7 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
|||||||
let mut sync_config = SyncConfig::default();
|
let mut sync_config = SyncConfig::default();
|
||||||
sync_config.network_id = match cmd.network_id {
|
sync_config.network_id = match cmd.network_id {
|
||||||
Some(id) => id,
|
Some(id) => id,
|
||||||
None => spec.network_id(),
|
None => spec.network_id() as usize,
|
||||||
};
|
};
|
||||||
if spec.subprotocol_name().len() != 3 {
|
if spec.subprotocol_name().len() != 3 {
|
||||||
warn!("Your chain specification's subprotocol length is not 3. Ignoring.");
|
warn!("Your chain specification's subprotocol length is not 3. Ignoring.");
|
||||||
|
@ -191,6 +191,7 @@ fn rpc_eth_logs() {
|
|||||||
data: vec![1,2,3],
|
data: vec![1,2,3],
|
||||||
},
|
},
|
||||||
transaction_index: 0,
|
transaction_index: 0,
|
||||||
|
transaction_log_index: 0,
|
||||||
transaction_hash: H256::default(),
|
transaction_hash: H256::default(),
|
||||||
log_index: 0,
|
log_index: 0,
|
||||||
}, LocalizedLogEntry {
|
}, LocalizedLogEntry {
|
||||||
@ -202,8 +203,9 @@ fn rpc_eth_logs() {
|
|||||||
data: vec![1,2,3],
|
data: vec![1,2,3],
|
||||||
},
|
},
|
||||||
transaction_index: 0,
|
transaction_index: 0,
|
||||||
|
transaction_log_index: 1,
|
||||||
transaction_hash: H256::default(),
|
transaction_hash: H256::default(),
|
||||||
log_index: 0,
|
log_index: 1,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
|
||||||
@ -211,8 +213,8 @@ fn rpc_eth_logs() {
|
|||||||
let request2 = r#"{"jsonrpc": "2.0", "method": "eth_getLogs", "params": [{"limit":1}], "id": 1}"#;
|
let request2 = r#"{"jsonrpc": "2.0", "method": "eth_getLogs", "params": [{"limit":1}], "id": 1}"#;
|
||||||
let request3 = r#"{"jsonrpc": "2.0", "method": "eth_getLogs", "params": [{"limit":0}], "id": 1}"#;
|
let request3 = r#"{"jsonrpc": "2.0", "method": "eth_getLogs", "params": [{"limit":0}], "id": 1}"#;
|
||||||
|
|
||||||
let response1 = r#"{"jsonrpc":"2.0","result":[{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x0","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"mined"},{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x0","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"mined"}],"id":1}"#;
|
let response1 = r#"{"jsonrpc":"2.0","result":[{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x0","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x0","type":"mined"},{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x1","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x1","type":"mined"}],"id":1}"#;
|
||||||
let response2 = r#"{"jsonrpc":"2.0","result":[{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x0","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"mined"}],"id":1}"#;
|
let response2 = r#"{"jsonrpc":"2.0","result":[{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x1","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x1","type":"mined"}],"id":1}"#;
|
||||||
let response3 = r#"{"jsonrpc":"2.0","result":[],"id":1}"#;
|
let response3 = r#"{"jsonrpc":"2.0","result":[],"id":1}"#;
|
||||||
|
|
||||||
assert_eq!(tester.io.handle_request_sync(request1), Some(response1.to_owned()));
|
assert_eq!(tester.io.handle_request_sync(request1), Some(response1.to_owned()));
|
||||||
@ -233,6 +235,7 @@ fn rpc_logs_filter() {
|
|||||||
data: vec![1,2,3],
|
data: vec![1,2,3],
|
||||||
},
|
},
|
||||||
transaction_index: 0,
|
transaction_index: 0,
|
||||||
|
transaction_log_index: 0,
|
||||||
transaction_hash: H256::default(),
|
transaction_hash: H256::default(),
|
||||||
log_index: 0,
|
log_index: 0,
|
||||||
}, LocalizedLogEntry {
|
}, LocalizedLogEntry {
|
||||||
@ -244,8 +247,9 @@ fn rpc_logs_filter() {
|
|||||||
data: vec![1,2,3],
|
data: vec![1,2,3],
|
||||||
},
|
},
|
||||||
transaction_index: 0,
|
transaction_index: 0,
|
||||||
|
transaction_log_index: 1,
|
||||||
transaction_hash: H256::default(),
|
transaction_hash: H256::default(),
|
||||||
log_index: 0,
|
log_index: 1,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
// Register filters first
|
// Register filters first
|
||||||
@ -259,8 +263,8 @@ fn rpc_logs_filter() {
|
|||||||
|
|
||||||
let request_changes1 = r#"{"jsonrpc": "2.0", "method": "eth_getFilterChanges", "params": ["0x0"], "id": 1}"#;
|
let request_changes1 = r#"{"jsonrpc": "2.0", "method": "eth_getFilterChanges", "params": ["0x0"], "id": 1}"#;
|
||||||
let request_changes2 = r#"{"jsonrpc": "2.0", "method": "eth_getFilterChanges", "params": ["0x1"], "id": 1}"#;
|
let request_changes2 = r#"{"jsonrpc": "2.0", "method": "eth_getFilterChanges", "params": ["0x1"], "id": 1}"#;
|
||||||
let response1 = r#"{"jsonrpc":"2.0","result":[{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x0","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"mined"},{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x0","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"mined"}],"id":1}"#;
|
let response1 = r#"{"jsonrpc":"2.0","result":[{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x0","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x0","type":"mined"},{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x1","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x1","type":"mined"}],"id":1}"#;
|
||||||
let response2 = r#"{"jsonrpc":"2.0","result":[{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x0","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"mined"}],"id":1}"#;
|
let response2 = r#"{"jsonrpc":"2.0","result":[{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x1","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x1","type":"mined"}],"id":1}"#;
|
||||||
|
|
||||||
assert_eq!(tester.io.handle_request_sync(request_changes1), Some(response1.to_owned()));
|
assert_eq!(tester.io.handle_request_sync(request_changes1), Some(response1.to_owned()));
|
||||||
assert_eq!(tester.io.handle_request_sync(request_changes2), Some(response2.to_owned()));
|
assert_eq!(tester.io.handle_request_sync(request_changes2), Some(response2.to_owned()));
|
||||||
@ -485,7 +489,7 @@ fn rpc_eth_pending_transaction_by_hash() {
|
|||||||
tester.miner.pending_transactions.lock().insert(H256::zero(), tx);
|
tester.miner.pending_transactions.lock().insert(H256::zero(), tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"v":0,"value":"0xa"},"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","networkId":null,"nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","standardV":"0x0","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"v":"0x1b","value":"0xa"},"id":1}"#;
|
||||||
let request = r#"{
|
let request = r#"{
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"method": "eth_getTransactionByHash",
|
"method": "eth_getTransactionByHash",
|
||||||
@ -761,6 +765,7 @@ fn rpc_eth_send_transaction() {
|
|||||||
|
|
||||||
assert_eq!(tester.io.handle_request_sync(&request), Some(response));
|
assert_eq!(tester.io.handle_request_sync(&request), Some(response));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rpc_eth_send_transaction_with_bad_to() {
|
fn rpc_eth_send_transaction_with_bad_to() {
|
||||||
let tester = EthTester::default();
|
let tester = EthTester::default();
|
||||||
@ -878,6 +883,7 @@ fn rpc_eth_transaction_receipt() {
|
|||||||
block_number: 0x4510c,
|
block_number: 0x4510c,
|
||||||
transaction_hash: H256::new(),
|
transaction_hash: H256::new(),
|
||||||
transaction_index: 0,
|
transaction_index: 0,
|
||||||
|
transaction_log_index: 0,
|
||||||
log_index: 1,
|
log_index: 1,
|
||||||
}],
|
}],
|
||||||
log_bloom: 0.into(),
|
log_bloom: 0.into(),
|
||||||
@ -894,7 +900,7 @@ fn rpc_eth_transaction_receipt() {
|
|||||||
"params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
|
"params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
|
||||||
"id": 1
|
"id": 1
|
||||||
}"#;
|
}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","contractAddress":null,"cumulativeGasUsed":"0x20","gasUsed":"0x10","logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","data":"0x","logIndex":"0x1","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"mined"}],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","root":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0"},"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","contractAddress":null,"cumulativeGasUsed":"0x20","gasUsed":"0x10","logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","data":"0x","logIndex":"0x1","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x0","type":"mined"}],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","root":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0"},"id":1}"#;
|
||||||
|
|
||||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ mod tests {
|
|||||||
fn test_serialize_block_transactions() {
|
fn test_serialize_block_transactions() {
|
||||||
let t = BlockTransactions::Full(vec![Transaction::default()]);
|
let t = BlockTransactions::Full(vec![Transaction::default()]);
|
||||||
let serialized = serde_json::to_string(&t).unwrap();
|
let serialized = serde_json::to_string(&t).unwrap();
|
||||||
assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"v":0,"r":"0x0000000000000000000000000000000000000000000000000000000000000000","s":"0x0000000000000000000000000000000000000000000000000000000000000000"}]"#);
|
assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"networkId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0"}]"#);
|
||||||
|
|
||||||
let t = BlockTransactions::Hashes(vec![H256::default().into()]);
|
let t = BlockTransactions::Hashes(vec![H256::default().into()]);
|
||||||
let serialized = serde_json::to_string(&t).unwrap();
|
let serialized = serde_json::to_string(&t).unwrap();
|
||||||
|
@ -124,7 +124,7 @@ impl Serialize for FilterChanges {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use util::hash::*;
|
use util::hash::H256;
|
||||||
use super::*;
|
use super::*;
|
||||||
use v1::types::BlockNumber;
|
use v1::types::BlockNumber;
|
||||||
use ethcore::filter::Filter as EthFilter;
|
use ethcore::filter::Filter as EthFilter;
|
||||||
|
@ -38,9 +38,12 @@ pub struct Log {
|
|||||||
/// Transaction Index
|
/// Transaction Index
|
||||||
#[serde(rename="transactionIndex")]
|
#[serde(rename="transactionIndex")]
|
||||||
pub transaction_index: Option<U256>,
|
pub transaction_index: Option<U256>,
|
||||||
/// Log Index
|
/// Log Index in Block
|
||||||
#[serde(rename="logIndex")]
|
#[serde(rename="logIndex")]
|
||||||
pub log_index: Option<U256>,
|
pub log_index: Option<U256>,
|
||||||
|
/// Log Index in Transaction
|
||||||
|
#[serde(rename="transactionLogIndex")]
|
||||||
|
pub transaction_log_index: Option<U256>,
|
||||||
/// Log Type
|
/// Log Type
|
||||||
#[serde(rename="type")]
|
#[serde(rename="type")]
|
||||||
pub log_type: String,
|
pub log_type: String,
|
||||||
@ -57,6 +60,7 @@ impl From<LocalizedLogEntry> for Log {
|
|||||||
transaction_hash: Some(e.transaction_hash.into()),
|
transaction_hash: Some(e.transaction_hash.into()),
|
||||||
transaction_index: Some(e.transaction_index.into()),
|
transaction_index: Some(e.transaction_index.into()),
|
||||||
log_index: Some(e.log_index.into()),
|
log_index: Some(e.log_index.into()),
|
||||||
|
transaction_log_index: Some(e.transaction_log_index.into()),
|
||||||
log_type: "mined".to_owned(),
|
log_type: "mined".to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,6 +77,7 @@ impl From<LogEntry> for Log {
|
|||||||
transaction_hash: None,
|
transaction_hash: None,
|
||||||
transaction_index: None,
|
transaction_index: None,
|
||||||
log_index: None,
|
log_index: None,
|
||||||
|
transaction_log_index: None,
|
||||||
log_type: "pending".to_owned(),
|
log_type: "pending".to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,7 +91,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn log_serialization() {
|
fn log_serialization() {
|
||||||
let s = r#"{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","logIndex":"0x1","type":"mined"}"#;
|
let s = r#"{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","logIndex":"0x1","transactionLogIndex":"0x1","type":"mined"}"#;
|
||||||
|
|
||||||
let log = Log {
|
let log = Log {
|
||||||
address: H160::from_str("33990122638b9132ca29c723bdf037f1a891a70c").unwrap(),
|
address: H160::from_str("33990122638b9132ca29c723bdf037f1a891a70c").unwrap(),
|
||||||
@ -99,6 +104,7 @@ mod tests {
|
|||||||
block_number: Some(U256::from(0x4510c)),
|
block_number: Some(U256::from(0x4510c)),
|
||||||
transaction_hash: Some(H256::default()),
|
transaction_hash: Some(H256::default()),
|
||||||
transaction_index: Some(U256::default()),
|
transaction_index: Some(U256::default()),
|
||||||
|
transaction_log_index: Some(1.into()),
|
||||||
log_index: Some(U256::from(1)),
|
log_index: Some(U256::from(1)),
|
||||||
log_type: "mined".to_owned(),
|
log_type: "mined".to_owned(),
|
||||||
};
|
};
|
||||||
|
@ -109,7 +109,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn receipt_serialization() {
|
fn receipt_serialization() {
|
||||||
let s = r#"{"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","cumulativeGasUsed":"0x20","gasUsed":"0x10","contractAddress":null,"logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","logIndex":"0x1","type":"mined"}],"root":"0x000000000000000000000000000000000000000000000000000000000000000a","logsBloom":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f"}"#;
|
let s = r#"{"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","cumulativeGasUsed":"0x20","gasUsed":"0x10","contractAddress":null,"logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","logIndex":"0x1","transactionLogIndex":null,"type":"mined"}],"root":"0x000000000000000000000000000000000000000000000000000000000000000a","logsBloom":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f"}"#;
|
||||||
|
|
||||||
let receipt = Receipt {
|
let receipt = Receipt {
|
||||||
transaction_hash: Some(0.into()),
|
transaction_hash: Some(0.into()),
|
||||||
@ -130,6 +130,7 @@ mod tests {
|
|||||||
block_number: Some(0x4510c.into()),
|
block_number: Some(0x4510c.into()),
|
||||||
transaction_hash: Some(0.into()),
|
transaction_hash: Some(0.into()),
|
||||||
transaction_index: Some(0.into()),
|
transaction_index: Some(0.into()),
|
||||||
|
transaction_log_index: None,
|
||||||
log_index: Some(1.into()),
|
log_index: Some(1.into()),
|
||||||
log_type: "mined".into(),
|
log_type: "mined".into(),
|
||||||
}],
|
}],
|
||||||
|
@ -54,12 +54,18 @@ pub struct Transaction {
|
|||||||
/// Public key of the signer.
|
/// Public key of the signer.
|
||||||
#[serde(rename="publicKey")]
|
#[serde(rename="publicKey")]
|
||||||
pub public_key: Option<H512>,
|
pub public_key: Option<H512>,
|
||||||
/// The V field of the signature.
|
/// The network id of the transaction, if any.
|
||||||
pub v: u8,
|
#[serde(rename="networkId")]
|
||||||
|
pub network_id: Option<u64>,
|
||||||
|
/// The standardised V field of the signature (0 or 1).
|
||||||
|
#[serde(rename="standardV")]
|
||||||
|
pub standard_v: U256,
|
||||||
|
/// The standardised V field of the signature.
|
||||||
|
pub v: U256,
|
||||||
/// The R field of the signature.
|
/// The R field of the signature.
|
||||||
pub r: H256,
|
pub r: U256,
|
||||||
/// The S field of the signature.
|
/// The S field of the signature.
|
||||||
pub s: H256,
|
pub s: U256,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LocalizedTransaction> for Transaction {
|
impl From<LocalizedTransaction> for Transaction {
|
||||||
@ -86,7 +92,9 @@ impl From<LocalizedTransaction> for Transaction {
|
|||||||
},
|
},
|
||||||
raw: ::rlp::encode(&t.signed).to_vec().into(),
|
raw: ::rlp::encode(&t.signed).to_vec().into(),
|
||||||
public_key: t.public_key().ok().map(Into::into),
|
public_key: t.public_key().ok().map(Into::into),
|
||||||
v: signature.v(),
|
network_id: t.network_id(),
|
||||||
|
standard_v: t.standard_v().into(),
|
||||||
|
v: t.original_v().into(),
|
||||||
r: signature.r().into(),
|
r: signature.r().into(),
|
||||||
s: signature.s().into(),
|
s: signature.s().into(),
|
||||||
}
|
}
|
||||||
@ -117,7 +125,9 @@ impl From<SignedTransaction> for Transaction {
|
|||||||
},
|
},
|
||||||
raw: ::rlp::encode(&t).to_vec().into(),
|
raw: ::rlp::encode(&t).to_vec().into(),
|
||||||
public_key: t.public_key().ok().map(Into::into),
|
public_key: t.public_key().ok().map(Into::into),
|
||||||
v: signature.v(),
|
network_id: t.network_id(),
|
||||||
|
standard_v: t.standard_v().into(),
|
||||||
|
v: t.original_v().into(),
|
||||||
r: signature.r().into(),
|
r: signature.r().into(),
|
||||||
s: signature.s().into(),
|
s: signature.s().into(),
|
||||||
}
|
}
|
||||||
@ -133,7 +143,7 @@ mod tests {
|
|||||||
fn test_transaction_serialize() {
|
fn test_transaction_serialize() {
|
||||||
let t = Transaction::default();
|
let t = Transaction::default();
|
||||||
let serialized = serde_json::to_string(&t).unwrap();
|
let serialized = serde_json::to_string(&t).unwrap();
|
||||||
assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"v":0,"r":"0x0000000000000000000000000000000000000000000000000000000000000000","s":"0x0000000000000000000000000000000000000000000000000000000000000000"}"#);
|
assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"networkId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0"}"#);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::thread;
|
|
||||||
use std::time;
|
use std::time;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use devtools::{http_client, RandomTempPath};
|
use devtools::{http_client, RandomTempPath};
|
||||||
|
@ -37,12 +37,12 @@
|
|||||||
//! implementations for even more speed, hidden behind the `x64_arithmetic`
|
//! implementations for even more speed, hidden behind the `x64_arithmetic`
|
||||||
//! feature flag.
|
//! feature flag.
|
||||||
|
|
||||||
use std::{mem, fmt};
|
use std::{mem, fmt, cmp};
|
||||||
use std::str::{FromStr};
|
use std::str::{FromStr};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::ops::{Shr, Shl, BitAnd, BitOr, BitXor, Not, Div, Rem, Mul, Add, Sub};
|
use std::ops::{Shr, Shl, BitAnd, BitOr, BitXor, Not, Div, Rem, Mul, Add, Sub};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use rustc_serialize::hex::{FromHex, FromHexError};
|
use rustc_serialize::hex::{ToHex, FromHex, FromHexError};
|
||||||
|
|
||||||
/// Conversion from decimal string error
|
/// Conversion from decimal string error
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
@ -520,8 +520,10 @@ pub trait Uint: Sized + Default + FromStr + From<u64> + fmt::Debug + fmt::Displa
|
|||||||
fn bit(&self, index: usize) -> bool;
|
fn bit(&self, index: usize) -> bool;
|
||||||
/// Return single byte
|
/// Return single byte
|
||||||
fn byte(&self, index: usize) -> u8;
|
fn byte(&self, index: usize) -> u8;
|
||||||
/// Convert U256 to the sequence of bytes with a big endian
|
/// Convert to the sequence of bytes with a big endian
|
||||||
fn to_big_endian(&self, bytes: &mut[u8]);
|
fn to_big_endian(&self, bytes: &mut[u8]);
|
||||||
|
/// Convert to a non-zero-prefixed hex representation (not prefixed by `0x`).
|
||||||
|
fn to_hex(&self) -> String;
|
||||||
/// Create `Uint(10**n)`
|
/// Create `Uint(10**n)`
|
||||||
fn exp10(n: usize) -> Self;
|
fn exp10(n: usize) -> Self;
|
||||||
/// Return eponentation `self**other`. Panic on overflow.
|
/// Return eponentation `self**other`. Panic on overflow.
|
||||||
@ -683,6 +685,17 @@ macro_rules! construct_uint {
|
|||||||
bytes[i] = (arr[pos] >> ((rev % 8) * 8)) as u8;
|
bytes[i] = (arr[pos] >> ((rev % 8) * 8)) as u8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
|
fn to_hex(&self) -> String {
|
||||||
|
if self.is_zero() { return "0".to_owned(); } // special case.
|
||||||
|
let mut bytes = [0u8; 8 * $n_words];
|
||||||
|
self.to_big_endian(&mut bytes);
|
||||||
|
let bp7 = self.bits() + 7;
|
||||||
|
let len = cmp::max(bp7 / 8, 1);
|
||||||
|
let bytes_hex = bytes[bytes.len() - len..].to_hex();
|
||||||
|
(&bytes_hex[1 - bp7 % 8 / 4..]).to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn exp10(n: usize) -> Self {
|
fn exp10(n: usize) -> Self {
|
||||||
match n {
|
match n {
|
||||||
@ -1636,7 +1649,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn uint256_pow () {
|
fn uint256_pow() {
|
||||||
assert_eq!(U256::from(10).pow(U256::from(0)), U256::from(1));
|
assert_eq!(U256::from(10).pow(U256::from(0)), U256::from(1));
|
||||||
assert_eq!(U256::from(10).pow(U256::from(1)), U256::from(10));
|
assert_eq!(U256::from(10).pow(U256::from(1)), U256::from(10));
|
||||||
assert_eq!(U256::from(10).pow(U256::from(2)), U256::from(100));
|
assert_eq!(U256::from(10).pow(U256::from(2)), U256::from(100));
|
||||||
@ -1646,12 +1659,24 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn uint256_pow_overflow_panic () {
|
fn uint256_pow_overflow_panic() {
|
||||||
U256::from(2).pow(U256::from(0x100));
|
U256::from(2).pow(U256::from(0x100));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn uint256_overflowing_pow () {
|
fn should_format_hex_correctly() {
|
||||||
|
assert_eq!(&U256::from(0).to_hex(), &"0");
|
||||||
|
assert_eq!(&U256::from(0x1).to_hex(), &"1");
|
||||||
|
assert_eq!(&U256::from(0xf).to_hex(), &"f");
|
||||||
|
assert_eq!(&U256::from(0x10).to_hex(), &"10");
|
||||||
|
assert_eq!(&U256::from(0xff).to_hex(), &"ff");
|
||||||
|
assert_eq!(&U256::from(0x100).to_hex(), &"100");
|
||||||
|
assert_eq!(&U256::from(0xfff).to_hex(), &"fff");
|
||||||
|
assert_eq!(&U256::from(0x1000).to_hex(), &"1000");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn uint256_overflowing_pow() {
|
||||||
// assert_eq!(
|
// assert_eq!(
|
||||||
// U256::from(2).overflowing_pow(U256::from(0xff)),
|
// U256::from(2).overflowing_pow(U256::from(0xff)),
|
||||||
// (U256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap(), false)
|
// (U256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap(), false)
|
||||||
|
Loading…
Reference in New Issue
Block a user