Merge branch 'master' into fo-6418-dont-export-bigint
# Conflicts: # dapps/src/tests/helpers/registrar.rs # ethcore/evm/src/interpreter/shared_cache.rs # ethcore/light/src/client/header_chain.rs # ethcore/light/src/client/mod.rs # ethcore/light/src/net/mod.rs # ethcore/light/src/on_demand/request.rs # ethcore/light/src/on_demand/tests.rs # ethcore/light/src/provider.rs # ethcore/node_filter/src/lib.rs # ethcore/src/block.rs # ethcore/src/blockchain/blockchain.rs # ethcore/src/client/test_client.rs # ethcore/src/engines/authority_round/mod.rs # ethcore/src/engines/basic_authority.rs # ethcore/src/engines/mod.rs # ethcore/src/engines/tendermint/mod.rs # ethcore/src/engines/validator_set/contract.rs # ethcore/src/engines/validator_set/multi.rs # ethcore/src/engines/validator_set/safe_contract.rs # ethcore/src/engines/vote_collector.rs # ethcore/src/miner/external.rs # ethcore/src/miner/miner.rs # ethcore/src/miner/service_transaction_checker.rs # ethcore/src/miner/work_notify.rs # ethcore/src/pod_account.rs # ethcore/src/pod_state.rs # ethcore/src/snapshot/block.rs # ethcore/src/snapshot/consensus/work.rs # ethcore/src/snapshot/mod.rs # ethcore/src/snapshot/service.rs # ethcore/src/spec/spec.rs # ethcore/src/state/backend.rs # ethcore/src/trace/db.rs # ethcore/src/verification/queue/mod.rs # ethcore/src/verification/verification.rs # parity/informant.rs # rpc/src/v1/helpers/dispatch.rs # rpc/src/v1/helpers/light_fetch.rs # rpc/src/v1/helpers/signing_queue.rs # rpc/src/v1/impls/eth.rs # rpc/src/v1/impls/eth_filter.rs # rpc/src/v1/impls/eth_pubsub.rs # rpc/src/v1/impls/light/eth.rs # rpc/src/v1/impls/signing.rs # rpc/src/v1/tests/helpers/miner_service.rs # rpc/src/v1/tests/helpers/snapshot_service.rs # rpc/src/v1/tests/helpers/sync_provider.rs # rpc/src/v1/tests/mocked/eth.rs # stratum/src/lib.rs # sync/src/blocks.rs # sync/src/chain.rs # sync/src/light_sync/mod.rs # sync/src/tests/helpers.rs # sync/src/tests/snapshot.rs # updater/src/updater.rs # util/src/lib.rs # util/triehash/src/lib.rs
This commit is contained in:
@@ -269,6 +269,34 @@ impl Impl for Ripemd160 {
|
||||
}
|
||||
}
|
||||
|
||||
// calculate modexp: exponentiation by squaring. the `num` crate has pow, but not modular.
|
||||
fn modexp(mut base: BigUint, mut exp: BigUint, modulus: BigUint) -> BigUint {
|
||||
use num::Integer;
|
||||
|
||||
match (base.is_zero(), exp.is_zero()) {
|
||||
(_, true) => return BigUint::one(), // n^0 % m
|
||||
(true, false) => return BigUint::zero(), // 0^n % m, n>0
|
||||
(false, false) if modulus <= BigUint::one() => return BigUint::zero(), // a^b % 1 = 0.
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let mut result = BigUint::one();
|
||||
base = base % &modulus;
|
||||
|
||||
// fast path for base divisible by modulus.
|
||||
if base.is_zero() { return BigUint::zero() }
|
||||
while !exp.is_zero() {
|
||||
if exp.is_odd() {
|
||||
result = (result * &base) % &modulus;
|
||||
}
|
||||
|
||||
exp = exp >> 1;
|
||||
base = (base.clone() * base) % &modulus;
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
impl Impl for ModexpImpl {
|
||||
fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> {
|
||||
let mut reader = input.chain(io::repeat(0));
|
||||
@@ -297,34 +325,6 @@ impl Impl for ModexpImpl {
|
||||
let exp = read_num(exp_len);
|
||||
let modulus = read_num(mod_len);
|
||||
|
||||
// calculate modexp: exponentiation by squaring. the `num` crate has pow, but not modular.
|
||||
fn modexp(mut base: BigUint, mut exp: BigUint, modulus: BigUint) -> BigUint {
|
||||
use num::Integer;
|
||||
|
||||
match (base.is_zero(), exp.is_zero()) {
|
||||
(_, true) => return BigUint::one(), // n^0 % m
|
||||
(true, false) => return BigUint::zero(), // 0^n % m, n>0
|
||||
(false, false) if modulus <= BigUint::one() => return BigUint::zero(), // a^b % 1 = 0.
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let mut result = BigUint::one();
|
||||
base = base % &modulus;
|
||||
|
||||
// fast path for base divisible by modulus.
|
||||
if base.is_zero() { return result }
|
||||
while !exp.is_zero() {
|
||||
if exp.is_odd() {
|
||||
result = (result * &base) % &modulus;
|
||||
}
|
||||
|
||||
exp = exp >> 1;
|
||||
base = (base.clone() * base) % &modulus;
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
// write output to given memory, left padded and same length as the modulus.
|
||||
let bytes = modexp(base, exp, modulus).to_bytes_be();
|
||||
|
||||
@@ -506,11 +506,45 @@ impl Impl for Bn128PairingImpl {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Builtin, Linear, ethereum_builtin, Pricer, Modexp};
|
||||
use super::{Builtin, Linear, ethereum_builtin, Pricer, Modexp, modexp as me};
|
||||
use ethjson;
|
||||
use bigint::prelude::U256;
|
||||
use util::BytesRef;
|
||||
use rustc_hex::FromHex;
|
||||
use num::{BigUint, Zero, One};
|
||||
|
||||
#[test]
|
||||
fn modexp_func() {
|
||||
// n^0 % m == 1
|
||||
let mut base = BigUint::parse_bytes(b"12345", 10).unwrap();
|
||||
let mut exp = BigUint::zero();
|
||||
let mut modulus = BigUint::parse_bytes(b"789", 10).unwrap();
|
||||
assert_eq!(me(base, exp, modulus), BigUint::one());
|
||||
|
||||
// 0^n % m == 0
|
||||
base = BigUint::zero();
|
||||
exp = BigUint::parse_bytes(b"12345", 10).unwrap();
|
||||
modulus = BigUint::parse_bytes(b"789", 10).unwrap();
|
||||
assert_eq!(me(base, exp, modulus), BigUint::zero());
|
||||
|
||||
// n^m % 1 == 0
|
||||
base = BigUint::parse_bytes(b"12345", 10).unwrap();
|
||||
exp = BigUint::parse_bytes(b"789", 10).unwrap();
|
||||
modulus = BigUint::one();
|
||||
assert_eq!(me(base, exp, modulus), BigUint::zero());
|
||||
|
||||
// if n % d == 0, then n^m % d == 0
|
||||
base = BigUint::parse_bytes(b"12345", 10).unwrap();
|
||||
exp = BigUint::parse_bytes(b"789", 10).unwrap();
|
||||
modulus = BigUint::parse_bytes(b"15", 10).unwrap();
|
||||
assert_eq!(me(base, exp, modulus), BigUint::zero());
|
||||
|
||||
// others
|
||||
base = BigUint::parse_bytes(b"12345", 10).unwrap();
|
||||
exp = BigUint::parse_bytes(b"789", 10).unwrap();
|
||||
modulus = BigUint::parse_bytes(b"97", 10).unwrap();
|
||||
assert_eq!(me(base, exp, modulus), BigUint::parse_bytes(b"55", 10).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn identity() {
|
||||
|
||||
Reference in New Issue
Block a user