Merge branch 'master' into lightsync
This commit is contained in:
		
						commit
						a48435ca60
					
				| @ -20,8 +20,8 @@ linux-stable: | ||||
|     - stable | ||||
|     - triggers | ||||
|   script: | ||||
|     - curl --data "secret=$RELEASES_SECRET" http://icarus.parity.io/push-release/$CI_BUILD_REF_NAME/$CI_BUILD_REF | ||||
|     - cargo build -j $(nproc) --release $CARGOFLAGS | ||||
|     - curl --data "secret=$RELEASES_SECRET" http://icarus.parity.io:1337/push-release/$CI_BUILD_REF_NAME/$CI_BUILD_REF | ||||
|     - cargo build -j $(nproc) --release --features final $CARGOFLAGS | ||||
|     - strip target/release/parity | ||||
|     - export SHA3=$(target/release/parity tools hash target/release/parity) | ||||
|     - md5sum target/release/parity > parity.md5 | ||||
| @ -38,7 +38,7 @@ linux-stable: | ||||
|     - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/parity.md5 --body parity.md5 | ||||
|     - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/"parity_"$VER"_amd64.deb" --body "parity_"$VER"_amd64.deb" | ||||
|     - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/"parity_"$VER"_amd64.deb.md5" --body "parity_"$VER"_amd64.deb.md5" | ||||
|     - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://icarus.parity.io/push-build/$CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu | ||||
|     - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://icarus.parity.io:1337/push-build/$CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu | ||||
|   tags: | ||||
|     - rust | ||||
|     - rust-stable | ||||
| @ -96,7 +96,7 @@ linux-centos: | ||||
|     - export CXX="g++" | ||||
|     - export CC="gcc" | ||||
|     - export PLATFORM=x86_64-unknown-centos-gnu | ||||
|     - cargo build -j $(nproc) --release $CARGOFLAGS | ||||
|     - cargo build -j $(nproc) --release --features final $CARGOFLAGS | ||||
|     - strip target/release/parity | ||||
|     - md5sum target/release/parity > parity.md5 | ||||
|     - export SHA3=$(target/release/parity tools hash target/release/parity) | ||||
| @ -106,7 +106,7 @@ linux-centos: | ||||
|     - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu | ||||
|     - aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/parity --body target/release/parity | ||||
|     - aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/parity.md5 --body parity.md5 | ||||
|     - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://icarus.parity.io/push-build/$CI_BUILD_REF_NAME/$PLATFORM | ||||
|     - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://icarus.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM | ||||
|   tags: | ||||
|     - rust | ||||
|     - rust-centos | ||||
| @ -127,7 +127,7 @@ linux-i686: | ||||
|     - export HOST_CXX=g++ | ||||
|     - export COMMIT=$(git rev-parse HEAD) | ||||
|     - export PLATFORM=i686-unknown-linux-gnu | ||||
|     - cargo build -j $(nproc) --target i686-unknown-linux-gnu --release $CARGOFLAGS | ||||
|     - cargo build -j $(nproc) --target i686-unknown-linux-gnu --features final --release $CARGOFLAGS | ||||
|     - strip target/$PLATFORM/release/parity | ||||
|     - md5sum target/$PLATFORM/release/parity > parity.md5 | ||||
|     - export SHA3=$(target/$PLATFORM/release/parity tools hash target/$PLATFORM/release/parity) | ||||
| @ -144,7 +144,7 @@ linux-i686: | ||||
|     - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/parity.md5 --body parity.md5 | ||||
|     - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_i386.deb" --body "parity_"$VER"_i386.deb" | ||||
|     - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_i386.deb.md5" --body "parity_"$VER"_i386.deb.md5" | ||||
|     - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://icarus.parity.io/push-build/$CI_BUILD_REF_NAME/$PLATFORM | ||||
|     - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://icarus.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM | ||||
|   tags: | ||||
|     - rust | ||||
|     - rust-i686 | ||||
| @ -171,7 +171,7 @@ linux-armv7: | ||||
|     - echo "[target.armv7-unknown-linux-gnueabihf]" >> .cargo/config | ||||
|     - echo "linker= \"arm-linux-gnueabihf-gcc\"" >> .cargo/config | ||||
|     - cat .cargo/config | ||||
|     - cargo build -j $(nproc) --target armv7-unknown-linux-gnueabihf --release $CARGOFLAGS | ||||
|     - cargo build -j $(nproc) --target armv7-unknown-linux-gnueabihf --features final --release $CARGOFLAGS | ||||
|     - arm-linux-gnueabihf-strip target/armv7-unknown-linux-gnueabihf/release/parity | ||||
|     - md5sum target/armv7-unknown-linux-gnueabihf/release/parity > parity.md5 | ||||
|     - sh scripts/deb-build.sh armhf | ||||
| @ -213,7 +213,7 @@ linux-arm: | ||||
|     - echo "[target.arm-unknown-linux-gnueabihf]" >> .cargo/config | ||||
|     - echo "linker= \"arm-linux-gnueabihf-gcc\"" >> .cargo/config | ||||
|     - cat .cargo/config | ||||
|     - cargo build -j $(nproc) --target arm-unknown-linux-gnueabihf --release $CARGOFLAGS | ||||
|     - cargo build -j $(nproc) --target arm-unknown-linux-gnueabihf --features final --release $CARGOFLAGS | ||||
|     - arm-linux-gnueabihf-strip target/arm-unknown-linux-gnueabihf/release/parity | ||||
|     - md5sum target/arm-unknown-linux-gnueabihf/release/parity > parity.md5 | ||||
|     - sh scripts/deb-build.sh armhf | ||||
| @ -255,7 +255,7 @@ linux-armv6: | ||||
|     - echo "[target.arm-unknown-linux-gnueabi]" >> .cargo/config | ||||
|     - echo "linker= \"arm-linux-gnueabi-gcc\"" >> .cargo/config | ||||
|     - cat .cargo/config | ||||
|     - cargo build -j $(nproc) --target arm-unknown-linux-gnueabi --release $CARGOFLAGS | ||||
|     - cargo build -j $(nproc) --target arm-unknown-linux-gnueabi --features final --release $CARGOFLAGS | ||||
|     - arm-linux-gnueabi-strip target/arm-unknown-linux-gnueabi/release/parity | ||||
|     - md5sum target/arm-unknown-linux-gnueabi/release/parity > parity.md5 | ||||
|     - aws configure set aws_access_key_id $s3_key | ||||
| @ -290,7 +290,7 @@ linux-aarch64: | ||||
|     - echo "[target.aarch64-unknown-linux-gnu]" >> .cargo/config | ||||
|     - echo "linker= \"aarch64-linux-gnu-gcc\"" >> .cargo/config | ||||
|     - cat .cargo/config | ||||
|     - cargo build -j $(nproc) --target aarch64-unknown-linux-gnu --release $CARGOFLAGS | ||||
|     - cargo build -j $(nproc) --target aarch64-unknown-linux-gnu --features final --release $CARGOFLAGS | ||||
|     - aarch64-linux-gnu-strip target/aarch64-unknown-linux-gnu/release/parity | ||||
|     - md5sum target/aarch64-unknown-linux-gnu/release/parity > parity.md5 | ||||
|     - sh scripts/deb-build.sh arm64 | ||||
| @ -323,8 +323,8 @@ darwin: | ||||
|   script: | ||||
|     - export COMMIT=$(git rev-parse HEAD) | ||||
|     - export PLATFORM=x86_64-apple-darwin | ||||
|     - cargo build -j 8 --release #$CARGOFLAGS | ||||
|     - cargo build -j 8 --release -p ethstore #$CARGOFLAGS | ||||
|     - cargo build -j 8 --features final --release #$CARGOFLAGS | ||||
|     - cargo build -j 8 --features final --release -p ethstore #$CARGOFLAGS | ||||
|     - rm -rf parity.md5 | ||||
|     - md5sum target/release/parity > parity.md5 | ||||
|     - export SHA3=$(target/release/parity tools hash target/release/parity) | ||||
| @ -340,7 +340,7 @@ darwin: | ||||
|     - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/parity.md5 --body parity.md5 | ||||
|     - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity-"$VER"-osx-installer-EXPERIMENTAL.pkg" --body "parity-"$VER"-osx-installer-EXPERIMENTAL.pkg" | ||||
|     - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity-"$VER"-osx-installer-EXPERIMENTAL.pkg.md5" --body "parity-"$VER"-osx-installer-EXPERIMENTAL.pkg.md5" | ||||
|     - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://icarus.parity.io/push-build/$CI_BUILD_REF_NAME/$PLATFORM | ||||
|     - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://icarus.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM | ||||
|   tags: | ||||
|     - osx | ||||
|   artifacts: | ||||
| @ -364,11 +364,12 @@ windows: | ||||
|     - set RUST_BACKTRACE=1 | ||||
|     - set RUSTFLAGS=%RUSTFLAGS% | ||||
|     - rustup default stable-x86_64-pc-windows-msvc | ||||
|     - cargo build --release #%CARGOFLAGS% | ||||
|     - FOR /F "tokens=* USEBACKQ" %%i IN ('target\release\parity.exe tools hash target\release\parity.exe') DO set SHA3=%%i | ||||
|     - cargo build --features final --release #%CARGOFLAGS% | ||||
|     - signtool sign /f %keyfile% /p %certpass% target\release\parity.exe | ||||
|     - target\release\parity.exe tools hash target\release\parity.exe > parity.sha3 | ||||
|     - set /P SHA3=<parity.sha3 | ||||
|     - curl -sL --url "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -o nsis\SimpleFC.dll | ||||
|     - curl -sL --url "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -o nsis\vc_redist.x64.exe | ||||
|     - signtool sign /f %keyfile% /p %certpass% target\release\parity.exe | ||||
|     - msbuild windows\ptray\ptray.vcxproj /p:Platform=x64 /p:Configuration=Release | ||||
|     - signtool sign /f %keyfile% /p %certpass% windows\ptray\x64\release\ptray.exe | ||||
|     - cd nsis | ||||
| @ -400,7 +401,7 @@ windows: | ||||
|     - aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/InstallParity.exe.md5 --body nsis\InstallParity.exe.md5 | ||||
|     - aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/win-installer.zip --body nsis\win-installer.zip | ||||
|     - aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/win-installer.zip.md5 --body nsis\win-installer.zip.md5 | ||||
|     - curl --data "commit=$CI_BUILD_REF&sha3=%SHA3%&filename=parity.exe&secret=%RELEASES_SECRET%" http://icarus.parity.io/push-build/$CI_BUILD_REF_NAME/%PLATFORM% | ||||
|     - curl --data "commit=%CI_BUILD_REF%&sha3=%SHA3%&filename=parity.exe&secret=%RELEASES_SECRET%" http://icarus.parity.io:1337/push-build/%CI_BUILD_REF_NAME%/%PLATFORM% | ||||
|   tags: | ||||
|    - rust-windows | ||||
|   artifacts: | ||||
| @ -425,7 +426,7 @@ test-darwin: | ||||
| test-windows: | ||||
|   stage: test | ||||
|   only: | ||||
| #    - triggers | ||||
|     - triggers | ||||
|   before_script: | ||||
|     - git submodule update --init --recursive | ||||
|   script: | ||||
|  | ||||
							
								
								
									
										28
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										28
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -885,18 +885,6 @@ name = "itoa" | ||||
| version = "0.1.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "jsonrpc-core" | ||||
| version = "3.0.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "jsonrpc-core" | ||||
| version = "4.0.0" | ||||
| @ -1349,7 +1337,7 @@ dependencies = [ | ||||
|  "ethcore-signer 1.5.0", | ||||
|  "ethcore-util 1.5.0", | ||||
|  "futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", | ||||
|  "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| @ -1398,17 +1386,7 @@ dependencies = [ | ||||
|  "ipc-common-types 1.5.0", | ||||
|  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "parity-hash-fetch 1.5.0", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "parking_lot" | ||||
| version = "0.2.8" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| @ -2236,7 +2214,6 @@ dependencies = [ | ||||
| "checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c" | ||||
| "checksum itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "086e1fa5fe48840b1cfdef3a20c7e3115599f8d5c4c87ef32a794a7cdd184d76" | ||||
| "checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1" | ||||
| "checksum jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3c5094610b07f28f3edaf3947b732dadb31dbba4941d4d0c1c7a8350208f4414" | ||||
| "checksum jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>" | ||||
| "checksum jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>" | ||||
| "checksum jsonrpc-ipc-server 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>" | ||||
| @ -2284,7 +2261,6 @@ dependencies = [ | ||||
| "checksum owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d91377085359426407a287ab16884a0111ba473aa6844ff01d4ec20ce3d75e7" | ||||
| "checksum parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98378dec0a185da2b7180308752f0bad73aaa949c3e0a3b0528d0e067945f7ab" | ||||
| "checksum parity-ui-precompiled 1.4.0 (git+https://github.com/ethcore/js-precompiled.git)" = "<none>" | ||||
| "checksum parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "968f685642555d2f7e202c48b8b11de80569e9bfea817f7f12d7c61aac62d4e6" | ||||
| "checksum parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e1435e7a2a00dfebededd6c6bdbd54008001e94b4a2aadd6aef0dc4c56317621" | ||||
| "checksum parking_lot_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb1b97670a2ffadce7c397fb80a3d687c4f3060140b885621ef1653d0e5d5068" | ||||
| "checksum phf 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "447d9d45f2e0b4a9b532e808365abf18fc211be6ca217202fcd45236ef12f026" | ||||
|  | ||||
| @ -61,7 +61,6 @@ daemonize = "0.2" | ||||
| 
 | ||||
| [features] | ||||
| default = ["ui-precompiled"] | ||||
| 
 | ||||
| ui = [ | ||||
| 	"dapps", | ||||
| 	"ethcore-dapps/ui", | ||||
| @ -72,7 +71,6 @@ ui-precompiled = [ | ||||
| 	"ethcore-signer/ui-precompiled", | ||||
| 	"ethcore-dapps/ui-precompiled", | ||||
| ] | ||||
| 
 | ||||
| dapps = ["ethcore-dapps"] | ||||
| ipc = ["ethcore/ipc", "ethsync/ipc"] | ||||
| jit = ["ethcore/jit"] | ||||
| @ -85,6 +83,7 @@ ethstore-cli = ["ethcore/ethstore-cli"] | ||||
| evm-debug = ["ethcore/evm-debug"] | ||||
| evm-debug-tests = ["ethcore/evm-debug-tests"] | ||||
| slow-blocks = ["ethcore/slow-blocks"] | ||||
| final = ["ethcore-util/final"] | ||||
| 
 | ||||
| [[bin]] | ||||
| path = "parity/main.rs" | ||||
|  | ||||
| @ -19,10 +19,10 @@ branches: | ||||
| install: | ||||
|   - git submodule update --init --recursive | ||||
|   - ps: Install-Product node 6 | ||||
|   - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.12.0-x86_64-pc-windows-msvc.exe" | ||||
|   - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.13.0-x86_64-pc-windows-msvc.exe" | ||||
|   - ps: Start-FileDownload "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -FileName nsis\SimpleFC.dll | ||||
|   - ps: Start-FileDownload "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -FileName nsis\vc_redist.x64.exe | ||||
|   - rust-1.12.0-x86_64-pc-windows-msvc.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" | ||||
|   - rust-1.13.0-x86_64-pc-windows-msvc.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" | ||||
|   - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin;C:\Program Files (x86)\NSIS;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin | ||||
|   - rustc -V | ||||
|   - cargo -V | ||||
|  | ||||
| @ -21,7 +21,7 @@ use ethcore::block_status::BlockStatus; | ||||
| use ethcore::ids::BlockId; | ||||
| use ethcore::header::Header; | ||||
| use ethcore::verification::queue::{self, HeaderQueue}; | ||||
| use ethcore::transaction::SignedTransaction; | ||||
| use ethcore::transaction::PendingTransaction; | ||||
| use ethcore::blockchain_info::BlockChainInfo; | ||||
| use ethcore::spec::Spec; | ||||
| use ethcore::service::ClientIoMessage; | ||||
| @ -75,7 +75,7 @@ pub trait LightChainClient: Send + Sync { | ||||
| pub struct Client { | ||||
| 	queue: HeaderQueue, | ||||
| 	chain: HeaderChain, | ||||
| 	tx_pool: Mutex<H256FastMap<SignedTransaction>>, | ||||
| 	tx_pool: Mutex<H256FastMap<PendingTransaction>>, | ||||
| 	import_lock: Mutex<()>, | ||||
| } | ||||
| 
 | ||||
| @ -96,13 +96,18 @@ impl Client { | ||||
| 	} | ||||
| 
 | ||||
| 	/// Import a local transaction.
 | ||||
| 	pub fn import_own_transaction(&self, tx: SignedTransaction) { | ||||
| 		self.tx_pool.lock().insert(tx.hash(), tx); | ||||
| 	pub fn import_own_transaction(&self, tx: PendingTransaction) { | ||||
| 		self.tx_pool.lock().insert(tx.transaction.hash(), tx); | ||||
| 	} | ||||
| 
 | ||||
| 	/// Fetch a vector of all pending transactions.
 | ||||
| 	pub fn pending_transactions(&self) -> Vec<SignedTransaction> { | ||||
| 		self.tx_pool.lock().values().cloned().collect() | ||||
| 	pub fn ready_transactions(&self) -> Vec<PendingTransaction> { | ||||
| 		let best_num = self.chain.best_block().number; | ||||
| 		self.tx_pool.lock() | ||||
| 			.values() | ||||
| 			.filter(|t| t.min_block.as_ref().map_or(true, |x| x <= &best_num)) | ||||
| 			.cloned() | ||||
| 			.collect() | ||||
| 	} | ||||
| 
 | ||||
| 	/// Inquire about the status of a given header.
 | ||||
| @ -234,7 +239,7 @@ impl Provider for Client { | ||||
| 		Vec::new() | ||||
| 	} | ||||
| 
 | ||||
| 	fn pending_transactions(&self) -> Vec<SignedTransaction> { | ||||
| 		Client::pending_transactions(self) | ||||
| 	fn ready_transactions(&self) -> Vec<PendingTransaction> { | ||||
| 		Client::ready_transactions(self) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -20,7 +20,7 @@ | ||||
| use ethcore::blockchain_info::BlockChainInfo; | ||||
| use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient}; | ||||
| use ethcore::ids::BlockId; | ||||
| use ethcore::transaction::SignedTransaction; | ||||
| use ethcore::transaction::PendingTransaction; | ||||
| use network::{PeerId, NodeId}; | ||||
| 
 | ||||
| use net::buffer_flow::FlowParams; | ||||
| @ -169,8 +169,8 @@ impl Provider for TestProvider { | ||||
| 		req.requests.into_iter().map(|_| ::rlp::EMPTY_LIST_RLP.to_vec()).collect() | ||||
| 	} | ||||
| 
 | ||||
| 	fn pending_transactions(&self) -> Vec<SignedTransaction> { | ||||
| 		self.0.client.pending_transactions() | ||||
| 	fn ready_transactions(&self) -> Vec<PendingTransaction> { | ||||
| 		self.0.client.ready_transactions() | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -19,7 +19,7 @@ | ||||
| 
 | ||||
| use ethcore::blockchain_info::BlockChainInfo; | ||||
| use ethcore::client::{BlockChainClient, ProvingBlockChainClient}; | ||||
| use ethcore::transaction::SignedTransaction; | ||||
| use ethcore::transaction::PendingTransaction; | ||||
| use ethcore::ids::BlockId; | ||||
| 
 | ||||
| use util::{Bytes, H256}; | ||||
| @ -79,7 +79,7 @@ pub trait Provider: Send + Sync { | ||||
| 	fn header_proofs(&self, req: request::HeaderProofs) -> Vec<Bytes>; | ||||
| 
 | ||||
| 	/// Provide pending transactions.
 | ||||
| 	fn pending_transactions(&self) -> Vec<SignedTransaction>; | ||||
| 	fn ready_transactions(&self) -> Vec<PendingTransaction>; | ||||
| } | ||||
| 
 | ||||
| // Implementation of a light client data provider for a client.
 | ||||
| @ -178,7 +178,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T { | ||||
| 		req.requests.into_iter().map(|_| ::rlp::EMPTY_LIST_RLP.to_vec()).collect() | ||||
| 	} | ||||
| 
 | ||||
| 	fn pending_transactions(&self) -> Vec<SignedTransaction> { | ||||
| 		BlockChainClient::pending_transactions(self) | ||||
| 	fn ready_transactions(&self) -> Vec<PendingTransaction> { | ||||
| 		BlockChainClient::ready_transactions(self) | ||||
| 	} | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| Subproject commit 9028c4801fd39fbb71a9796979182549a24e81c8 | ||||
| Subproject commit e8f4624b7f1a15c63674eecf577c7ab76c3b16be | ||||
| @ -44,7 +44,7 @@ use env_info::LastHashes; | ||||
| use verification; | ||||
| use verification::{PreverifiedBlock, Verifier}; | ||||
| use block::*; | ||||
| use transaction::{LocalizedTransaction, SignedTransaction, Transaction, Action}; | ||||
| use transaction::{LocalizedTransaction, SignedTransaction, Transaction, PendingTransaction, Action}; | ||||
| use blockchain::extras::TransactionAddress; | ||||
| use types::filter::Filter; | ||||
| use types::mode::Mode as IpcMode; | ||||
| @ -1334,8 +1334,8 @@ impl BlockChainClient for Client { | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	fn pending_transactions(&self) -> Vec<SignedTransaction> { | ||||
| 		self.miner.pending_transactions(self.chain.read().best_block_number()) | ||||
| 	fn ready_transactions(&self) -> Vec<PendingTransaction> { | ||||
| 		self.miner.ready_transactions(self.chain.read().best_block_number()) | ||||
| 	} | ||||
| 
 | ||||
| 	fn queue_consensus_message(&self, message: Bytes) { | ||||
|  | ||||
| @ -21,7 +21,7 @@ use util::*; | ||||
| use rlp::*; | ||||
| use ethkey::{Generator, Random}; | ||||
| use devtools::*; | ||||
| use transaction::{Transaction, LocalizedTransaction, SignedTransaction, Action}; | ||||
| use transaction::{Transaction, LocalizedTransaction, SignedTransaction, PendingTransaction, Action}; | ||||
| use blockchain::TreeRoute; | ||||
| use client::{ | ||||
| 	BlockChainClient, MiningBlockChainClient, BlockChainInfo, BlockStatus, BlockId, | ||||
| @ -688,8 +688,8 @@ impl BlockChainClient for TestBlockChainClient { | ||||
| 
 | ||||
| 	fn broadcast_consensus_message(&self, _message: Bytes) {} | ||||
| 
 | ||||
| 	fn pending_transactions(&self) -> Vec<SignedTransaction> { | ||||
| 		self.miner.pending_transactions(self.chain_info().best_block_number) | ||||
| 	fn ready_transactions(&self) -> Vec<PendingTransaction> { | ||||
| 		self.miner.ready_transactions(self.chain_info().best_block_number) | ||||
| 	} | ||||
| 
 | ||||
| 	fn signing_network_id(&self) -> Option<u64> { None } | ||||
|  | ||||
| @ -21,7 +21,7 @@ use blockchain::TreeRoute; | ||||
| use verification::queue::QueueInfo as BlockQueueInfo; | ||||
| use block::{OpenBlock, SealedBlock}; | ||||
| use header::{BlockNumber}; | ||||
| use transaction::{LocalizedTransaction, SignedTransaction}; | ||||
| use transaction::{LocalizedTransaction, SignedTransaction, PendingTransaction}; | ||||
| use log_entry::LocalizedLogEntry; | ||||
| use filter::Filter; | ||||
| use views::{BlockView}; | ||||
| @ -211,8 +211,8 @@ pub trait BlockChainClient : Sync + Send { | ||||
| 	/// Used by PoA to communicate with peers.
 | ||||
| 	fn broadcast_consensus_message(&self, message: Bytes); | ||||
| 
 | ||||
| 	/// list all transactions
 | ||||
| 	fn pending_transactions(&self) -> Vec<SignedTransaction>; | ||||
| 	/// List all transactions that are allowed into the next block.
 | ||||
| 	fn ready_transactions(&self) -> Vec<PendingTransaction>; | ||||
| 
 | ||||
| 	/// Sorted list of transaction gas prices from at least last sample_size blocks.
 | ||||
| 	fn gas_price_corpus(&self, sample_size: usize) -> Vec<U256> { | ||||
|  | ||||
| @ -178,15 +178,15 @@ impl Engine for Ethash { | ||||
| 		let gas_limit = { | ||||
| 			let gas_limit = parent.gas_limit().clone(); | ||||
| 			let bound_divisor = self.ethash_params.gas_limit_bound_divisor; | ||||
| 			let lower_limit = gas_limit - gas_limit / bound_divisor + 1.into(); | ||||
| 			let upper_limit = gas_limit + gas_limit / bound_divisor - 1.into(); | ||||
| 			if gas_limit < gas_floor_target { | ||||
| 				min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into()) | ||||
| 				min(gas_floor_target, upper_limit) | ||||
| 			} else if gas_limit > gas_ceil_target { | ||||
| 				max(gas_ceil_target, gas_limit - gas_limit / bound_divisor + 1.into()) | ||||
| 				max(gas_ceil_target, lower_limit) | ||||
| 			} else { | ||||
| 				min(gas_ceil_target, | ||||
| 					max(gas_floor_target, | ||||
| 						gas_limit - gas_limit / bound_divisor + 1.into() + | ||||
| 							(header.gas_used().clone() * 6.into() / 5.into()) / bound_divisor)) | ||||
| 				max(gas_floor_target, min(min(gas_ceil_target, upper_limit), 
 | ||||
| 					lower_limit + (header.gas_used().clone() * 6.into() / 5.into()) / bound_divisor)) | ||||
| 			} | ||||
| 		}; | ||||
| 		header.set_difficulty(difficulty); | ||||
|  | ||||
| @ -115,7 +115,7 @@ impl BanningTransactionQueue { | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		self.queue.add(transaction, TransactionOrigin::External, account_details, gas_estimator) | ||||
| 		self.queue.add(transaction, TransactionOrigin::External, None, account_details, gas_estimator) | ||||
| 	} | ||||
| 
 | ||||
| 	/// Ban transaction with given hash.
 | ||||
| @ -263,7 +263,7 @@ mod tests { | ||||
| 		let mut txq = queue(); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		txq.queue().add(tx, TransactionOrigin::External, &default_account_details, &gas_required).unwrap(); | ||||
| 		txq.queue().add(tx, TransactionOrigin::External, None, &default_account_details, &gas_required).unwrap(); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		// should also deref to queue
 | ||||
|  | ||||
| @ -28,7 +28,7 @@ use client::TransactionImportResult; | ||||
| use executive::contract_address; | ||||
| use block::{ClosedBlock, IsBlock, Block}; | ||||
| use error::*; | ||||
| use transaction::{Action, SignedTransaction}; | ||||
| use transaction::{Action, SignedTransaction, PendingTransaction}; | ||||
| use receipt::{Receipt, RichReceipt}; | ||||
| use spec::Spec; | ||||
| use engines::{Engine, Seal}; | ||||
| @ -320,11 +320,12 @@ impl Miner { | ||||
| 		} | ||||
| 
 | ||||
| 		let _timer = PerfTimer::new("prepare_block"); | ||||
| 		let chain_info = chain.chain_info(); | ||||
| 		let (transactions, mut open_block, original_work_hash) = { | ||||
| 			let transactions = {self.transaction_queue.lock().top_transactions()}; | ||||
| 			let transactions = {self.transaction_queue.lock().top_transactions_at(chain_info.best_block_number)}; | ||||
| 			let mut sealing_work = self.sealing_work.lock(); | ||||
| 			let last_work_hash = sealing_work.queue.peek_last_ref().map(|pb| pb.block().fields().header.hash()); | ||||
| 			let best_hash = chain.best_block_header().sha3(); | ||||
| 			let best_hash = chain_info.best_block_hash; | ||||
| /* | ||||
| 			// check to see if last ClosedBlock in would_seals is actually same parent block.
 | ||||
| 			// if so
 | ||||
| @ -577,8 +578,14 @@ impl Miner { | ||||
| 		prepare_new | ||||
| 	} | ||||
| 
 | ||||
| 	fn add_transactions_to_queue(&self, chain: &MiningBlockChainClient, transactions: Vec<SignedTransaction>, default_origin: TransactionOrigin, transaction_queue: &mut BanningTransactionQueue) -> | ||||
| 		Vec<Result<TransactionImportResult, Error>> { | ||||
| 	fn add_transactions_to_queue( | ||||
| 		&self, | ||||
| 		chain: &MiningBlockChainClient, | ||||
| 		transactions: Vec<SignedTransaction>, | ||||
| 		default_origin: TransactionOrigin, | ||||
| 		min_block: Option<BlockNumber>, | ||||
| 		transaction_queue: &mut BanningTransactionQueue) | ||||
| 		-> Vec<Result<TransactionImportResult, Error>> { | ||||
| 
 | ||||
| 		let fetch_account = |a: &Address| AccountDetails { | ||||
| 			nonce: chain.latest_nonce(a), | ||||
| @ -613,7 +620,7 @@ impl Miner { | ||||
| 
 | ||||
| 						match origin { | ||||
| 							TransactionOrigin::Local | TransactionOrigin::RetractedBlock => { | ||||
| 								transaction_queue.add(tx, origin, &fetch_account, &gas_required) | ||||
| 								transaction_queue.add(tx, origin, min_block, &fetch_account, &gas_required) | ||||
| 							}, | ||||
| 							TransactionOrigin::External => { | ||||
| 								transaction_queue.add_with_banlist(tx, &fetch_account, &gas_required) | ||||
| @ -839,7 +846,7 @@ impl MinerService for Miner { | ||||
| 		let results = { | ||||
| 			let mut transaction_queue = self.transaction_queue.lock(); | ||||
| 			self.add_transactions_to_queue( | ||||
| 				chain, transactions, TransactionOrigin::External, &mut transaction_queue | ||||
| 				chain, transactions, TransactionOrigin::External, None, &mut transaction_queue | ||||
| 			) | ||||
| 		}; | ||||
| 
 | ||||
| @ -857,17 +864,17 @@ impl MinerService for Miner { | ||||
| 	fn import_own_transaction( | ||||
| 		&self, | ||||
| 		chain: &MiningBlockChainClient, | ||||
| 		transaction: SignedTransaction, | ||||
| 		pending: PendingTransaction, | ||||
| 	) -> Result<TransactionImportResult, Error> { | ||||
| 
 | ||||
| 		let hash = transaction.hash(); | ||||
| 		trace!(target: "own_tx", "Importing transaction: {:?}", transaction); | ||||
| 		let hash = pending.transaction.hash(); | ||||
| 		trace!(target: "own_tx", "Importing transaction: {:?}", pending); | ||||
| 
 | ||||
| 		let imported = { | ||||
| 			// Be sure to release the lock before we call prepare_work_sealing
 | ||||
| 			let mut transaction_queue = self.transaction_queue.lock(); | ||||
| 			let import = self.add_transactions_to_queue( | ||||
| 				chain, vec![transaction], TransactionOrigin::Local, &mut transaction_queue | ||||
| 				chain, vec![pending.transaction], TransactionOrigin::Local, pending.min_block, &mut transaction_queue | ||||
| 			).pop().expect("one result returned per added transaction; one added => one result; qed"); | ||||
| 
 | ||||
| 			match import { | ||||
| @ -902,9 +909,9 @@ impl MinerService for Miner { | ||||
| 		imported | ||||
| 	} | ||||
| 
 | ||||
| 	fn all_transactions(&self) -> Vec<SignedTransaction> { | ||||
| 	fn pending_transactions(&self) -> Vec<PendingTransaction> { | ||||
| 		let queue = self.transaction_queue.lock(); | ||||
| 		queue.top_transactions() | ||||
| 		queue.pending_transactions(BlockNumber::max_value()) | ||||
| 	} | ||||
| 
 | ||||
| 	fn local_transactions(&self) -> BTreeMap<H256, LocalTransactionStatus> { | ||||
| @ -915,22 +922,26 @@ impl MinerService for Miner { | ||||
| 			.collect() | ||||
| 	} | ||||
| 
 | ||||
| 	fn pending_transactions(&self, best_block: BlockNumber) -> Vec<SignedTransaction> { | ||||
| 	fn future_transactions(&self) -> Vec<PendingTransaction> { | ||||
| 		self.transaction_queue.lock().future_transactions() | ||||
| 	} | ||||
| 
 | ||||
| 	fn ready_transactions(&self, best_block: BlockNumber) -> Vec<PendingTransaction> { | ||||
| 		let queue = self.transaction_queue.lock(); | ||||
| 		match self.options.pending_set { | ||||
| 			PendingSet::AlwaysQueue => queue.top_transactions(), | ||||
| 			PendingSet::AlwaysQueue => queue.pending_transactions(best_block), | ||||
| 			PendingSet::SealingOrElseQueue => { | ||||
| 				self.from_pending_block( | ||||
| 					best_block, | ||||
| 					|| queue.top_transactions(), | ||||
| 					|sealing| sealing.transactions().to_owned() | ||||
| 					|| queue.pending_transactions(best_block), | ||||
| 					|sealing| sealing.transactions().iter().map(|t| t.clone().into()).collect() | ||||
| 				) | ||||
| 			}, | ||||
| 			PendingSet::AlwaysSealing => { | ||||
| 				self.from_pending_block( | ||||
| 					best_block, | ||||
| 					|| vec![], | ||||
| 					|sealing| sealing.transactions().to_owned() | ||||
| 					|sealing| sealing.transactions().iter().map(|t| t.clone().into()).collect() | ||||
| 				) | ||||
| 			}, | ||||
| 		} | ||||
| @ -1126,7 +1137,7 @@ impl MinerService for Miner { | ||||
| 				}).for_each(|txs| { | ||||
| 					let mut transaction_queue = self.transaction_queue.lock(); | ||||
| 					let _ = self.add_transactions_to_queue( | ||||
| 						chain, txs, TransactionOrigin::RetractedBlock, &mut transaction_queue | ||||
| 						chain, txs, TransactionOrigin::RetractedBlock, None, &mut transaction_queue | ||||
| 					); | ||||
| 				}); | ||||
| 		} | ||||
| @ -1159,7 +1170,7 @@ mod tests { | ||||
| 	use ethkey::{Generator, Random}; | ||||
| 	use client::{BlockChainClient, TestBlockChainClient, EachBlockWith, TransactionImportResult}; | ||||
| 	use header::BlockNumber; | ||||
| 	use types::transaction::{Transaction, SignedTransaction, Action}; | ||||
| 	use types::transaction::{Transaction, SignedTransaction, PendingTransaction, Action}; | ||||
| 	use spec::Spec; | ||||
| 	use tests::helpers::{generate_dummy_client}; | ||||
| 
 | ||||
| @ -1238,12 +1249,12 @@ mod tests { | ||||
| 		let transaction = transaction(); | ||||
| 		let best_block = 0; | ||||
| 		// when
 | ||||
| 		let res = miner.import_own_transaction(&client, transaction); | ||||
| 		let res = miner.import_own_transaction(&client, PendingTransaction::new(transaction, None)); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(res.unwrap(), TransactionImportResult::Current); | ||||
| 		assert_eq!(miner.all_transactions().len(), 1); | ||||
| 		assert_eq!(miner.pending_transactions(best_block).len(), 1); | ||||
| 		assert_eq!(miner.pending_transactions().len(), 1); | ||||
| 		assert_eq!(miner.ready_transactions(best_block).len(), 1); | ||||
| 		assert_eq!(miner.pending_transactions_hashes(best_block).len(), 1); | ||||
| 		assert_eq!(miner.pending_receipts(best_block).len(), 1); | ||||
| 		// This method will let us know if pending block was created (before calling that method)
 | ||||
| @ -1258,12 +1269,12 @@ mod tests { | ||||
| 		let transaction = transaction(); | ||||
| 		let best_block = 10; | ||||
| 		// when
 | ||||
| 		let res = miner.import_own_transaction(&client, transaction); | ||||
| 		let res = miner.import_own_transaction(&client, PendingTransaction::new(transaction, None)); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(res.unwrap(), TransactionImportResult::Current); | ||||
| 		assert_eq!(miner.all_transactions().len(), 1); | ||||
| 		assert_eq!(miner.pending_transactions(best_block).len(), 0); | ||||
| 		assert_eq!(miner.pending_transactions().len(), 1); | ||||
| 		assert_eq!(miner.ready_transactions(best_block).len(), 0); | ||||
| 		assert_eq!(miner.pending_transactions_hashes(best_block).len(), 0); | ||||
| 		assert_eq!(miner.pending_receipts(best_block).len(), 0); | ||||
| 	} | ||||
| @ -1280,9 +1291,9 @@ mod tests { | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(res.unwrap(), TransactionImportResult::Current); | ||||
| 		assert_eq!(miner.all_transactions().len(), 1); | ||||
| 		assert_eq!(miner.pending_transactions().len(), 1); | ||||
| 		assert_eq!(miner.pending_transactions_hashes(best_block).len(), 0); | ||||
| 		assert_eq!(miner.pending_transactions(best_block).len(), 0); | ||||
| 		assert_eq!(miner.ready_transactions(best_block).len(), 0); | ||||
| 		assert_eq!(miner.pending_receipts(best_block).len(), 0); | ||||
| 		// This method will let us know if pending block was created (before calling that method)
 | ||||
| 		assert!(miner.prepare_work_sealing(&client)); | ||||
| @ -1315,7 +1326,7 @@ mod tests { | ||||
| 		assert!(miner.pending_block().is_none()); | ||||
| 		assert_eq!(client.chain_info().best_block_number, 3 as BlockNumber); | ||||
| 
 | ||||
| 		assert_eq!(miner.import_own_transaction(client, transaction()).unwrap(), TransactionImportResult::Current); | ||||
| 		assert_eq!(miner.import_own_transaction(client, PendingTransaction::new(transaction(), None)).unwrap(), TransactionImportResult::Current); | ||||
| 
 | ||||
| 		miner.update_sealing(client); | ||||
| 		client.flush_queue(); | ||||
|  | ||||
| @ -62,7 +62,7 @@ use block::ClosedBlock; | ||||
| use header::BlockNumber; | ||||
| use receipt::{RichReceipt, Receipt}; | ||||
| use error::{Error, CallError}; | ||||
| use transaction::SignedTransaction; | ||||
| use transaction::{SignedTransaction, PendingTransaction}; | ||||
| 
 | ||||
| /// Miner client API
 | ||||
| pub trait MinerService : Send + Sync { | ||||
| @ -118,7 +118,7 @@ pub trait MinerService : Send + Sync { | ||||
| 		Vec<Result<TransactionImportResult, Error>>; | ||||
| 
 | ||||
| 	/// Imports own (node owner) transaction to queue.
 | ||||
| 	fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: SignedTransaction) -> | ||||
| 	fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: PendingTransaction) -> | ||||
| 		Result<TransactionImportResult, Error>; | ||||
| 
 | ||||
| 	/// Returns hashes of transactions currently in pending
 | ||||
| @ -144,11 +144,14 @@ pub trait MinerService : Send + Sync { | ||||
| 	/// Query pending transactions for hash.
 | ||||
| 	fn transaction(&self, best_block: BlockNumber, hash: &H256) -> Option<SignedTransaction>; | ||||
| 
 | ||||
| 	/// Get a list of all transactions.
 | ||||
| 	fn all_transactions(&self) -> Vec<SignedTransaction>; | ||||
| 	/// Get a list of all pending transactions in the queue.
 | ||||
| 	fn pending_transactions(&self) -> Vec<PendingTransaction>; | ||||
| 
 | ||||
| 	/// Get a list of all pending transactions.
 | ||||
| 	fn pending_transactions(&self, best_block: BlockNumber) -> Vec<SignedTransaction>; | ||||
| 	/// Get a list of all transactions that can go into the given block.
 | ||||
| 	fn ready_transactions(&self, best_block: BlockNumber) -> Vec<PendingTransaction>; | ||||
| 
 | ||||
| 	/// Get a list of all future transactions.
 | ||||
| 	fn future_transactions(&self) -> Vec<PendingTransaction>; | ||||
| 
 | ||||
| 	/// Get a list of local transactions with statuses.
 | ||||
| 	fn local_transactions(&self) -> BTreeMap<H256, LocalTransactionStatus>; | ||||
|  | ||||
| @ -51,8 +51,8 @@ | ||||
| //!		let gas_estimator = |_tx: &SignedTransaction| 2.into();
 | ||||
| //!
 | ||||
| //!		let mut txq = TransactionQueue::default();
 | ||||
| //!		txq.add(st2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap();
 | ||||
| //!		txq.add(st1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap();
 | ||||
| //!		txq.add(st2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | ||||
| //!		txq.add(st1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | ||||
| //!
 | ||||
| //!		// Check status
 | ||||
| //!		assert_eq!(txq.status().pending, 2);
 | ||||
| @ -94,6 +94,7 @@ use util::table::Table; | ||||
| use transaction::*; | ||||
| use error::{Error, TransactionError}; | ||||
| use client::TransactionImportResult; | ||||
| use header::BlockNumber; | ||||
| use miner::local_transactions::{LocalTransactionsList, Status as LocalTransactionStatus}; | ||||
| 
 | ||||
| /// Transaction origin
 | ||||
| @ -253,18 +254,21 @@ impl Ord for TransactionOrder { | ||||
| /// Verified transaction (with sender)
 | ||||
| #[derive(Debug)] | ||||
| struct VerifiedTransaction { | ||||
| 	/// Transaction
 | ||||
| 	/// Transaction.
 | ||||
| 	transaction: SignedTransaction, | ||||
| 	/// transaction origin
 | ||||
| 	/// Transaction origin.
 | ||||
| 	origin: TransactionOrigin, | ||||
| 	/// Delay until specifid block.
 | ||||
| 	min_block: Option<BlockNumber>, | ||||
| } | ||||
| 
 | ||||
| impl VerifiedTransaction { | ||||
| 	fn new(transaction: SignedTransaction, origin: TransactionOrigin) -> Result<Self, Error> { | ||||
| 	fn new(transaction: SignedTransaction, origin: TransactionOrigin, min_block: Option<BlockNumber>) -> Result<Self, Error> { | ||||
| 		try!(transaction.sender()); | ||||
| 		Ok(VerifiedTransaction { | ||||
| 			transaction: transaction, | ||||
| 			origin: origin, | ||||
| 			min_block: min_block, | ||||
| 		}) | ||||
| 	} | ||||
| 
 | ||||
| @ -620,6 +624,7 @@ impl TransactionQueue { | ||||
| 		&mut self, | ||||
| 		tx: SignedTransaction, | ||||
| 		origin: TransactionOrigin, | ||||
| 		min_block: Option<BlockNumber>, | ||||
| 		fetch_account: &F, | ||||
| 		gas_estimator: &G, | ||||
| 	) -> Result<TransactionImportResult, Error> where | ||||
| @ -630,7 +635,7 @@ impl TransactionQueue { | ||||
| 			let hash = tx.hash(); | ||||
| 			let cloned_tx = tx.clone(); | ||||
| 
 | ||||
| 			let result = self.add_internal(tx, origin, fetch_account, gas_estimator); | ||||
| 			let result = self.add_internal(tx, origin, min_block, fetch_account, gas_estimator); | ||||
| 			match result { | ||||
| 				Ok(TransactionImportResult::Current) => { | ||||
| 					self.local_transactions.mark_pending(hash); | ||||
| @ -651,7 +656,7 @@ impl TransactionQueue { | ||||
| 			} | ||||
| 			result | ||||
| 		} else { | ||||
| 			self.add_internal(tx, origin, fetch_account, gas_estimator) | ||||
| 			self.add_internal(tx, origin, min_block, fetch_account, gas_estimator) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| @ -660,6 +665,7 @@ impl TransactionQueue { | ||||
| 		&mut self, | ||||
| 		tx: SignedTransaction, | ||||
| 		origin: TransactionOrigin, | ||||
| 		min_block: Option<BlockNumber>, | ||||
| 		fetch_account: &F, | ||||
| 		gas_estimator: &G, | ||||
| 	) -> Result<TransactionImportResult, Error> where | ||||
| @ -728,7 +734,7 @@ impl TransactionQueue { | ||||
| 		// Verify signature
 | ||||
| 		try!(tx.check_low_s()); | ||||
| 
 | ||||
| 		let vtx = try!(VerifiedTransaction::new(tx, origin)); | ||||
| 		let vtx = try!(VerifiedTransaction::new(tx, origin, min_block)); | ||||
| 		let client_account = fetch_account(&vtx.sender()); | ||||
| 
 | ||||
| 		let cost = vtx.transaction.value + vtx.transaction.gas_price * vtx.transaction.gas; | ||||
| @ -968,10 +974,48 @@ impl TransactionQueue { | ||||
| 
 | ||||
| 	/// Returns top transactions from the queue ordered by priority.
 | ||||
| 	pub fn top_transactions(&self) -> Vec<SignedTransaction> { | ||||
| 		self.current.by_priority | ||||
| 		self.top_transactions_at(BlockNumber::max_value()) | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	fn filter_pending_transaction<F>(&self, best_block: BlockNumber, mut f: F) | ||||
| 		where F: FnMut(&VerifiedTransaction) { | ||||
| 
 | ||||
| 		let mut delayed = HashSet::new(); | ||||
| 		for t in self.current.by_priority.iter() { | ||||
| 			let tx = self.by_hash.get(&t.hash).expect("All transactions in `current` and `future` are always included in `by_hash`"); | ||||
| 			let sender = tx.sender(); | ||||
| 			if delayed.contains(&sender) { | ||||
| 				continue; | ||||
| 			} | ||||
| 			if tx.min_block.unwrap_or(0) > best_block { | ||||
| 				delayed.insert(sender); | ||||
| 				continue; | ||||
| 			} | ||||
| 			f(&tx); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/// Returns top transactions from the queue ordered by priority.
 | ||||
| 	pub fn top_transactions_at(&self, best_block: BlockNumber) -> Vec<SignedTransaction> { | ||||
| 		let mut r = Vec::new(); | ||||
| 		self.filter_pending_transaction(best_block, |tx| r.push(tx.transaction.clone())); | ||||
| 		r | ||||
| 	} | ||||
| 
 | ||||
| 	/// Return all ready transactions.
 | ||||
| 	pub fn pending_transactions(&self, best_block: BlockNumber) -> Vec<PendingTransaction> { | ||||
| 		let mut r = Vec::new(); | ||||
| 		self.filter_pending_transaction(best_block, |tx| r.push(PendingTransaction::new(tx.transaction.clone(), tx.min_block))); | ||||
| 		r | ||||
| 	} | ||||
| 
 | ||||
| 	/// Return all ready transactions.
 | ||||
| 	pub fn future_transactions(&self) -> Vec<PendingTransaction> { | ||||
| 		self.future.by_priority | ||||
| 			.iter() | ||||
| 			.map(|t| self.by_hash.get(&t.hash).expect("All transactions in `current` and `future` are always included in `by_hash`")) | ||||
| 			.map(|t| t.transaction.clone()) | ||||
| 			.map(|t| PendingTransaction { transaction: t.transaction.clone(), min_block: t.min_block }) | ||||
| 			.collect() | ||||
| 	} | ||||
| 
 | ||||
| @ -980,15 +1024,6 @@ impl TransactionQueue { | ||||
| 		self.local_transactions.all_transactions() | ||||
| 	} | ||||
| 
 | ||||
| 	#[cfg(test)] | ||||
| 	fn future_transactions(&self) -> Vec<SignedTransaction> { | ||||
| 		self.future.by_priority | ||||
| 			.iter() | ||||
| 			.map(|t| self.by_hash.get(&t.hash).expect("All transactions in `current` and `future` are always included in `by_hash`")) | ||||
| 			.map(|t| t.transaction.clone()) | ||||
| 			.collect() | ||||
| 	} | ||||
| 
 | ||||
| 	/// Returns hashes of all transactions from current, ordered by priority.
 | ||||
| 	pub fn pending_hashes(&self) -> Vec<H256> { | ||||
| 		self.current.by_priority | ||||
| @ -1353,14 +1388,14 @@ mod test { | ||||
| 		let (tx1, tx2) = new_tx_pair(123.into(), 1.into(), 1.into(), 0.into()); | ||||
| 		let sender = tx1.sender().unwrap(); | ||||
| 		let nonce = tx1.nonce; | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.status().pending, 2); | ||||
| 		assert_eq!(txq.last_nonce(&sender), Some(nonce + 1.into())); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let tx = new_tx(123.into(), 1.into()); | ||||
| 		let res = txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator); | ||||
| 		let res = txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		// No longer the case as we don't even consider a transaction that isn't above a full
 | ||||
| @ -1392,12 +1427,12 @@ mod test { | ||||
| 			gas_limit: !U256::zero(), | ||||
| 		}; | ||||
| 		let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); | ||||
| 		let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External).unwrap(); | ||||
| 		let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External).unwrap(); | ||||
| 		let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External, None).unwrap(); | ||||
| 		let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External, None).unwrap(); | ||||
| 		let mut by_hash = { | ||||
| 			let mut x = HashMap::new(); | ||||
| 			let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External).unwrap(); | ||||
| 			let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External).unwrap(); | ||||
| 			let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External, None).unwrap(); | ||||
| 			let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External, None).unwrap(); | ||||
| 			x.insert(tx1.hash(), tx1); | ||||
| 			x.insert(tx2.hash(), tx2); | ||||
| 			x | ||||
| @ -1435,12 +1470,12 @@ mod test { | ||||
| 		// Create two transactions with same nonce
 | ||||
| 		// (same hash)
 | ||||
| 		let (tx1, tx2) = new_tx_pair_default(0.into(), 0.into()); | ||||
| 		let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External).unwrap(); | ||||
| 		let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External).unwrap(); | ||||
| 		let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External, None).unwrap(); | ||||
| 		let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External, None).unwrap(); | ||||
| 		let by_hash = { | ||||
| 			let mut x = HashMap::new(); | ||||
| 			let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External).unwrap(); | ||||
| 			let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External).unwrap(); | ||||
| 			let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External, None).unwrap(); | ||||
| 			let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External, None).unwrap(); | ||||
| 			x.insert(tx1.hash(), tx1); | ||||
| 			x.insert(tx2.hash(), tx2); | ||||
| 			x | ||||
| @ -1482,10 +1517,10 @@ mod test { | ||||
| 			gas_limit: !U256::zero(), | ||||
| 		}; | ||||
| 		let tx = new_tx_default(); | ||||
| 		let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External).unwrap(); | ||||
| 		let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External, None).unwrap(); | ||||
| 		let order1 = TransactionOrder::for_transaction(&tx1, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly); | ||||
| 		assert!(set.insert(tx1.sender(), tx1.nonce(), order1).is_none()); | ||||
| 		let tx2 = VerifiedTransaction::new(tx, TransactionOrigin::External).unwrap(); | ||||
| 		let tx2 = VerifiedTransaction::new(tx, TransactionOrigin::External, None).unwrap(); | ||||
| 		let order2 = TransactionOrder::for_transaction(&tx2, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly); | ||||
| 		assert!(set.insert(tx2.sender(), tx2.nonce(), order2).is_some()); | ||||
| 	} | ||||
| @ -1502,7 +1537,7 @@ mod test { | ||||
| 
 | ||||
| 		assert_eq!(set.gas_price_entry_limit(), 0.into()); | ||||
| 		let tx = new_tx_default(); | ||||
| 		let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External).unwrap(); | ||||
| 		let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External, None).unwrap(); | ||||
| 		let order1 = TransactionOrder::for_transaction(&tx1, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly); | ||||
| 		assert!(set.insert(tx1.sender(), tx1.nonce(), order1.clone()).is_none()); | ||||
| 		assert_eq!(set.gas_price_entry_limit(), 2.into()); | ||||
| @ -1517,12 +1552,12 @@ mod test { | ||||
| 			!U256::zero() }; | ||||
| 
 | ||||
| 		// First insert one transaction to future
 | ||||
| 		let res = txq.add(tx, TransactionOrigin::External, &prev_nonce, &gas_estimator); | ||||
| 		let res = txq.add(tx, TransactionOrigin::External, None, &prev_nonce, &gas_estimator); | ||||
| 		assert_eq!(res.unwrap(), TransactionImportResult::Future); | ||||
| 		assert_eq!(txq.status().future, 1); | ||||
| 
 | ||||
| 		// now import second transaction to current
 | ||||
| 		let res = txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator); | ||||
| 		let res = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator); | ||||
| 
 | ||||
| 		// and then there should be only one transaction in current (the one with higher gas_price)
 | ||||
| 		assert_eq!(res.unwrap(), TransactionImportResult::Current); | ||||
| @ -1542,12 +1577,12 @@ mod test { | ||||
| 			!U256::zero() }; | ||||
| 
 | ||||
| 		// First insert one transaction to future
 | ||||
| 		let res = txq.add(tx.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator); | ||||
| 		let res = txq.add(tx.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator); | ||||
| 		assert_eq!(res.unwrap(), TransactionImportResult::Future); | ||||
| 		assert_eq!(txq.status().future, 1); | ||||
| 
 | ||||
| 		// now import second transaction to current
 | ||||
| 		let res = txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator); | ||||
| 		let res = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(res.unwrap(), TransactionImportResult::Current); | ||||
| @ -1566,7 +1601,7 @@ mod test { | ||||
| 		let tx = new_tx_default(); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let res = txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator); | ||||
| 		let res = txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(res.unwrap(), TransactionImportResult::Current); | ||||
| @ -1585,10 +1620,10 @@ mod test { | ||||
| 		txq.set_minimal_gas_price(15.into()); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let res1 = txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator); | ||||
| 		let res2 = txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator); | ||||
| 		let res3 = txq.add(tx3, TransactionOrigin::External, &default_account_details, &gas_estimator); | ||||
| 		let res4 = txq.add(tx4, TransactionOrigin::External, &default_account_details, &gas_estimator); | ||||
| 		let res1 = txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator); | ||||
| 		let res2 = txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator); | ||||
| 		let res3 = txq.add(tx3, TransactionOrigin::External, None, &default_account_details, &gas_estimator); | ||||
| 		let res4 = txq.add(tx4, TransactionOrigin::External, None, &default_account_details, &gas_estimator); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(res1.unwrap(), TransactionImportResult::Current); | ||||
| @ -1619,10 +1654,10 @@ mod test { | ||||
| 		txq.set_minimal_gas_price(15.into()); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let res1 = txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator); | ||||
| 		let res2 = txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator); | ||||
| 		let res3 = txq.add(tx3, TransactionOrigin::External, &default_account_details, &gas_estimator); | ||||
| 		let res4 = txq.add(tx4, TransactionOrigin::External, &default_account_details, &gas_estimator); | ||||
| 		let res1 = txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator); | ||||
| 		let res2 = txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator); | ||||
| 		let res3 = txq.add(tx3, TransactionOrigin::External, None, &default_account_details, &gas_estimator); | ||||
| 		let res4 = txq.add(tx4, TransactionOrigin::External, None, &default_account_details, &gas_estimator); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(res1.unwrap(), TransactionImportResult::Current); | ||||
| @ -1665,7 +1700,7 @@ mod test { | ||||
| 		txq.set_gas_limit(limit); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let res = txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator); | ||||
| 		let res = txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(unwrap_tx_err(res), TransactionError::GasLimitExceeded { | ||||
| @ -1689,7 +1724,7 @@ mod test { | ||||
| 		}; | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let res = txq.add(tx, TransactionOrigin::External, &account, &gas_estimator); | ||||
| 		let res = txq.add(tx, TransactionOrigin::External, None, &account, &gas_estimator); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientBalance { | ||||
| @ -1709,7 +1744,7 @@ mod test { | ||||
| 		txq.set_minimal_gas_price(tx.gas_price + U256::one()); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let res = txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator); | ||||
| 		let res = txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientGasPrice { | ||||
| @ -1729,7 +1764,7 @@ mod test { | ||||
| 		txq.set_minimal_gas_price(tx.gas_price + U256::one()); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let res = txq.add(tx, TransactionOrigin::Local, &default_account_details, &gas_estimator); | ||||
| 		let res = txq.add(tx, TransactionOrigin::Local, None, &default_account_details, &gas_estimator); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(res.unwrap(), TransactionImportResult::Current); | ||||
| @ -1759,7 +1794,7 @@ mod test { | ||||
| 			rlp::decode(s.as_raw()) | ||||
| 		}; | ||||
| 		// when
 | ||||
| 		let res = txq.add(stx, TransactionOrigin::External, &default_account_details, &gas_estimator); | ||||
| 		let res = txq.add(stx, TransactionOrigin::External, None, &default_account_details, &gas_estimator); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert!(res.is_err()); | ||||
| @ -1773,8 +1808,8 @@ mod test { | ||||
| 		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		let top = txq.top_transactions(); | ||||
| @ -1793,9 +1828,9 @@ mod test { | ||||
| 
 | ||||
| 		// when
 | ||||
| 		// first insert the one with higher gas price
 | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		// then the one with lower gas price, but local
 | ||||
| 		txq.add(tx.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		let top = txq.top_transactions(); | ||||
| @ -1812,15 +1847,15 @@ mod test { | ||||
| 		// the second one has same nonce but higher `gas_price`
 | ||||
| 		let (_, tx0) = new_similar_tx_pair(); | ||||
| 
 | ||||
| 		txq.add(tx0.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx0.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		// the one with higher gas price is first
 | ||||
| 		assert_eq!(txq.top_transactions()[0], tx0); | ||||
| 		assert_eq!(txq.top_transactions()[1], tx1); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		// insert second as local
 | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		// the order should be updated
 | ||||
| @ -1839,9 +1874,9 @@ mod test { | ||||
| 
 | ||||
| 		// when
 | ||||
| 		// first insert local one with higher gas price
 | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		// then the one with lower gas price, but from retracted block
 | ||||
| 		txq.add(tx.clone(), TransactionOrigin::RetractedBlock, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx.clone(), TransactionOrigin::RetractedBlock, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		let top = txq.top_transactions(); | ||||
| @ -1857,8 +1892,8 @@ mod test { | ||||
| 		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		let top = txq.top_transactions(); | ||||
| @ -1877,10 +1912,10 @@ mod test { | ||||
| 		let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into()); | ||||
| 
 | ||||
| 		// insert everything
 | ||||
| 		txq.add(txa.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); | ||||
| 		txq.add(txb.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); | ||||
| 		txq.add(txa.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); | ||||
| 		txq.add(txb.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		assert_eq!(txq.status().future, 4); | ||||
| 
 | ||||
| @ -1889,10 +1924,10 @@ mod test { | ||||
| 
 | ||||
| 		// then
 | ||||
| 		let top = txq.future_transactions(); | ||||
| 		assert_eq!(top[0], txa); | ||||
| 		assert_eq!(top[1], txb); | ||||
| 		assert_eq!(top[2], tx1); | ||||
| 		assert_eq!(top[3], tx2); | ||||
| 		assert_eq!(top[0].transaction, txa); | ||||
| 		assert_eq!(top[1].transaction, txb); | ||||
| 		assert_eq!(top[2].transaction, tx1); | ||||
| 		assert_eq!(top[3].transaction, tx2); | ||||
| 		assert_eq!(top.len(), 4); | ||||
| 	} | ||||
| 
 | ||||
| @ -1905,10 +1940,10 @@ mod test { | ||||
| 		let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into()); | ||||
| 
 | ||||
| 		// insert everything
 | ||||
| 		txq.add(txa.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(txb.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(txa.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(txb.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		let top = txq.top_transactions(); | ||||
| 		assert_eq!(top[0], tx1); | ||||
| @ -1938,10 +1973,10 @@ mod test { | ||||
| 		let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into()); | ||||
| 
 | ||||
| 		// insert everything
 | ||||
| 		txq.add(txa.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(txb.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(txa.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(txb.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		let top = txq.top_transactions(); | ||||
| 		assert_eq!(top[0], tx1); | ||||
| @ -1970,8 +2005,8 @@ mod test { | ||||
| 		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		let top = txq.pending_hashes(); | ||||
| @ -1988,8 +2023,8 @@ mod test { | ||||
| 		let (tx, tx2) = new_tx_pair_default(2.into(), 0.into()); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let res1 = txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		let res2 = txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		let res1 = txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		let res2 = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(res1, TransactionImportResult::Current); | ||||
| @ -2002,6 +2037,26 @@ mod test { | ||||
| 		assert_eq!(top[0], tx); | ||||
| 	} | ||||
| 
 | ||||
| 	#[test] | ||||
| 	fn should_handle_min_block() { | ||||
| 		// given
 | ||||
| 		let mut txq = TransactionQueue::default(); | ||||
| 
 | ||||
| 		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let res1 = txq.add(tx.clone(), TransactionOrigin::External, Some(1), &default_account_details, &gas_estimator).unwrap(); | ||||
| 		let res2 = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(res1, TransactionImportResult::Current); | ||||
| 		assert_eq!(res2, TransactionImportResult::Current); | ||||
| 		let top = txq.top_transactions_at(0); | ||||
| 		assert_eq!(top.len(), 0); | ||||
| 		let top = txq.top_transactions_at(1); | ||||
| 		assert_eq!(top.len(), 2); | ||||
| 	} | ||||
| 
 | ||||
| 	#[test] | ||||
| 	fn should_correctly_update_futures_when_removing() { | ||||
| 		// given
 | ||||
| @ -2012,8 +2067,8 @@ mod test { | ||||
| 		let mut txq = TransactionQueue::default(); | ||||
| 
 | ||||
| 		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); | ||||
| 		txq.add(tx.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.status().future, 2); | ||||
| 
 | ||||
| 		// when
 | ||||
| @ -2035,13 +2090,13 @@ mod test { | ||||
| 		let tx1 = new_unsigned_tx(124.into(), default_gas_val(), 1.into()).sign(secret, None); | ||||
| 		let tx2 = new_unsigned_tx(125.into(), default_gas_val(), 1.into()).sign(secret, None); | ||||
| 
 | ||||
| 		txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.status().pending, 1); | ||||
| 		txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.status().future, 1); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		let stats = txq.status(); | ||||
| @ -2057,8 +2112,8 @@ mod test { | ||||
| 		// given
 | ||||
| 		let mut txq2 = TransactionQueue::default(); | ||||
| 		let (tx, tx2) = new_tx_pair_default(3.into(), 0.into()); | ||||
| 		txq2.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq2.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq2.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq2.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq2.status().pending, 1); | ||||
| 		assert_eq!(txq2.status().future, 1); | ||||
| 
 | ||||
| @ -2079,10 +2134,10 @@ mod test { | ||||
| 		let mut txq = TransactionQueue::default(); | ||||
| 		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); | ||||
| 		let tx3 = new_tx_default(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.status().future, 1); | ||||
| 		txq.add(tx3.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.status().pending, 3); | ||||
| 
 | ||||
| 		// when
 | ||||
| @ -2101,8 +2156,8 @@ mod test { | ||||
| 		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); | ||||
| 
 | ||||
| 		// add
 | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		let stats = txq.status(); | ||||
| 		assert_eq!(stats.pending, 2); | ||||
| 
 | ||||
| @ -2121,11 +2176,11 @@ mod test { | ||||
| 		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); | ||||
| 		let sender = tx.sender().unwrap(); | ||||
| 		let nonce = tx.nonce; | ||||
| 		txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.status().pending, 1); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let res = txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator); | ||||
| 		let res = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		let t = txq.top_transactions(); | ||||
| @ -2142,14 +2197,14 @@ mod test { | ||||
| 		txq.current.set_limit(10); | ||||
| 		let (tx1, tx2) = new_tx_pair_default(4.into(), 1.into()); | ||||
| 		let (tx3, tx4) = new_tx_pair_default(4.into(), 2.into()); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx3.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.status().pending, 2); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.status().future, 1); | ||||
| 		txq.add(tx4.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx4.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(txq.status().future, 1); | ||||
| @ -2160,11 +2215,11 @@ mod test { | ||||
| 		let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 100, default_gas_val() * U256::from(2), !U256::zero()); | ||||
| 		let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1)); | ||||
| 		let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2)); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx3.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		// limited by gas
 | ||||
| 		txq.add(tx4.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap_err(); | ||||
| 		txq.add(tx4.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap_err(); | ||||
| 		assert_eq!(txq.status().pending, 2); | ||||
| 	} | ||||
| 
 | ||||
| @ -2174,12 +2229,12 @@ mod test { | ||||
| 		let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1)); | ||||
| 		let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2)); | ||||
| 		let (tx5, _) = new_tx_pair_default(U256::from(1), U256::from(2)); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		// Not accepted because of limit
 | ||||
| 		txq.add(tx5.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap_err(); | ||||
| 		txq.add(tx3.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx4.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx5.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap_err(); | ||||
| 		txq.add(tx3.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx4.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.status().pending, 4); | ||||
| 	} | ||||
| 
 | ||||
| @ -2191,7 +2246,7 @@ mod test { | ||||
| 		let fetch_last_nonce = |_a: &Address| AccountDetails { nonce: last_nonce, balance: !U256::zero() }; | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let res = txq.add(tx, TransactionOrigin::External, &fetch_last_nonce, &gas_estimator); | ||||
| 		let res = txq.add(tx, TransactionOrigin::External, None, &fetch_last_nonce, &gas_estimator); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(unwrap_tx_err(res), TransactionError::Old); | ||||
| @ -2207,12 +2262,12 @@ mod test { | ||||
| 			balance: !U256::zero() }; | ||||
| 		let mut txq = TransactionQueue::default(); | ||||
| 		let (_tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.status().future, 1); | ||||
| 		assert_eq!(txq.status().pending, 0); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let res = txq.add(tx2.clone(), TransactionOrigin::External, &nonce, &gas_estimator); | ||||
| 		let res = txq.add(tx2.clone(), TransactionOrigin::External, None, &nonce, &gas_estimator); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(unwrap_tx_err(res), TransactionError::AlreadyImported); | ||||
| @ -2226,15 +2281,15 @@ mod test { | ||||
| 		// given
 | ||||
| 		let mut txq = TransactionQueue::default(); | ||||
| 		let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.status().pending, 2); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		txq.remove_invalid(&tx1.hash(), &default_account_details); | ||||
| 		assert_eq!(txq.status().pending, 0); | ||||
| 		assert_eq!(txq.status().future, 1); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		let stats = txq.status(); | ||||
| @ -2248,10 +2303,10 @@ mod test { | ||||
| 		let mut txq = TransactionQueue::default(); | ||||
| 		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); | ||||
| 		let tx3 = new_tx_default(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.status().future, 1); | ||||
| 		txq.add(tx3.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.status().pending, 3); | ||||
| 
 | ||||
| 		// when
 | ||||
| @ -2278,8 +2333,8 @@ mod test { | ||||
| 		}; | ||||
| 
 | ||||
| 		// when
 | ||||
| 		txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		let stats = txq.status(); | ||||
| @ -2306,10 +2361,10 @@ mod test { | ||||
| 		}; | ||||
| 
 | ||||
| 		// when
 | ||||
| 		txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.status().future, 1); | ||||
| 		txq.add(tx0, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx0, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		let stats = txq.status(); | ||||
| @ -2327,8 +2382,8 @@ mod test { | ||||
| 			!U256::zero() }; | ||||
| 		let mut txq = TransactionQueue::default(); | ||||
| 		let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, &previous_nonce, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2, TransactionOrigin::External, &previous_nonce, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1.clone(), TransactionOrigin::External, None, &previous_nonce, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2, TransactionOrigin::External, None, &previous_nonce, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.status().future, 2); | ||||
| 
 | ||||
| 		// when
 | ||||
| @ -2359,7 +2414,7 @@ mod test { | ||||
| 		let details = |_a: &Address| AccountDetails { nonce: nonce, balance: !U256::zero() }; | ||||
| 
 | ||||
| 		// when
 | ||||
| 		txq.add(tx, TransactionOrigin::External, &details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx, TransactionOrigin::External, None, &details, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(txq.last_nonce(&from), Some(nonce)); | ||||
| @ -2374,7 +2429,7 @@ mod test { | ||||
| 		let details1 = |_a: &Address| AccountDetails { nonce: nonce1, balance: !U256::zero() }; | ||||
| 
 | ||||
| 		// Insert first transaction
 | ||||
| 		txq.add(tx1, TransactionOrigin::External, &details1, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1, TransactionOrigin::External, None, &details1, &gas_estimator).unwrap(); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		txq.remove_all(tx2.sender().unwrap(), nonce2 + U256::one()); | ||||
| @ -2394,9 +2449,9 @@ mod test { | ||||
| 
 | ||||
| 		// when
 | ||||
| 		// Insert first transaction
 | ||||
| 		assert_eq!(txq.add(tx1, TransactionOrigin::External, &details1, &gas_estimator).unwrap(), TransactionImportResult::Current); | ||||
| 		assert_eq!(txq.add(tx1, TransactionOrigin::External, None, &details1, &gas_estimator).unwrap(), TransactionImportResult::Current); | ||||
| 		// Second should go to future
 | ||||
| 		assert_eq!(txq.add(tx2, TransactionOrigin::External, &details1, &gas_estimator).unwrap(), TransactionImportResult::Future); | ||||
| 		assert_eq!(txq.add(tx2, TransactionOrigin::External, None, &details1, &gas_estimator).unwrap(), TransactionImportResult::Future); | ||||
| 		// Now block is imported
 | ||||
| 		txq.remove_all(sender, nonce2 - U256::from(1)); | ||||
| 		// tx2 should be not be promoted to current
 | ||||
| @ -2415,9 +2470,9 @@ mod test { | ||||
| 		assert_eq!(txq.has_local_pending_transactions(), false); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		assert_eq!(txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(), TransactionImportResult::Current); | ||||
| 		assert_eq!(txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(), TransactionImportResult::Current); | ||||
| 		assert_eq!(txq.has_local_pending_transactions(), false); | ||||
| 		assert_eq!(txq.add(tx2, TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(), TransactionImportResult::Current); | ||||
| 		assert_eq!(txq.add(tx2, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(), TransactionImportResult::Current); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(txq.has_local_pending_transactions(), true); | ||||
| @ -2432,8 +2487,8 @@ mod test { | ||||
| 			default_account_details(a).balance }; | ||||
| 
 | ||||
| 		// when
 | ||||
| 		assert_eq!(txq.add(tx2, TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(), TransactionImportResult::Future); | ||||
| 		assert_eq!(txq.add(tx1.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(), TransactionImportResult::Future); | ||||
| 		assert_eq!(txq.add(tx2, TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(), TransactionImportResult::Future); | ||||
| 		assert_eq!(txq.add(tx1.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(), TransactionImportResult::Future); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(txq.future.by_priority.len(), 1); | ||||
| @ -2458,14 +2513,14 @@ mod test { | ||||
| 			(tx.sign(secret, None), tx2.sign(secret, None), tx2_2.sign(secret, None), tx3.sign(secret, None)) | ||||
| 		}; | ||||
| 		let sender = tx1.sender().unwrap(); | ||||
| 		txq.add(tx1, TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2, TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx3, TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx3, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.future.by_priority.len(), 0); | ||||
| 		assert_eq!(txq.current.by_priority.len(), 3); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let res = txq.add(tx2_2, TransactionOrigin::Local, &default_account_details, &gas_estimator); | ||||
| 		let res = txq.add(tx2_2, TransactionOrigin::Local, None, &default_account_details, &gas_estimator); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(txq.last_nonce(&sender).unwrap(), 125.into()); | ||||
| @ -2481,8 +2536,8 @@ mod test { | ||||
| 		let high_gas = |_: &SignedTransaction| 100_001.into(); | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let res1 = txq.add(tx1, TransactionOrigin::Local, &default_account_details, &gas_estimator); | ||||
| 		let res2 = txq.add(tx2, TransactionOrigin::Local, &default_account_details, &high_gas); | ||||
| 		let res1 = txq.add(tx1, TransactionOrigin::Local, None, &default_account_details, &gas_estimator); | ||||
| 		let res2 = txq.add(tx2, TransactionOrigin::Local, None, &default_account_details, &high_gas); | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(res1.unwrap(), TransactionImportResult::Current); | ||||
| @ -2502,10 +2557,10 @@ mod test { | ||||
| 		let nonce1 = tx1.nonce; | ||||
| 
 | ||||
| 		// Insert all transactions
 | ||||
| 		txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx3, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx4, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx3, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		txq.add(tx4, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); | ||||
| 		assert_eq!(txq.top_transactions().len(), 4); | ||||
| 
 | ||||
| 		// when
 | ||||
|  | ||||
| @ -28,6 +28,9 @@ use rlp::{Rlp, View}; | ||||
| use spec::Spec; | ||||
| use views::BlockView; | ||||
| use util::stats::Histogram; | ||||
| use ethkey::KeyPair; | ||||
| use transaction::{PendingTransaction, Transaction, Action}; | ||||
| use miner::MinerService; | ||||
| 
 | ||||
| #[test] | ||||
| fn imports_from_empty() { | ||||
| @ -284,3 +287,37 @@ fn change_history_size() { | ||||
| 	let client = Client::new(config, &test_spec, dir.as_path(), Arc::new(Miner::with_spec(&test_spec)), IoChannel::disconnected(), &db_config).unwrap(); | ||||
| 	assert_eq!(client.state().balance(&address), 100.into()); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn does_not_propagate_delayed_transactions() { | ||||
| 	let key = KeyPair::from_secret("test".sha3()).unwrap(); | ||||
| 	let secret = key.secret(); | ||||
| 	let tx0 = PendingTransaction::new(Transaction { | ||||
| 		nonce: 0.into(), | ||||
| 		gas_price: 0.into(), | ||||
| 		gas: 21000.into(), | ||||
| 		action: Action::Call(Address::default()), | ||||
| 		value: 0.into(), | ||||
| 		data: Vec::new(), | ||||
| 	}.sign(secret, None), Some(2)); | ||||
| 	let tx1 = PendingTransaction::new(Transaction { | ||||
| 		nonce: 1.into(), | ||||
| 		gas_price: 0.into(), | ||||
| 		gas: 21000.into(), | ||||
| 		action: Action::Call(Address::default()), | ||||
| 		value: 0.into(), | ||||
| 		data: Vec::new(), | ||||
| 	}.sign(secret, None), None); | ||||
| 	let client_result = generate_dummy_client(1); | ||||
| 	let client = client_result.reference(); | ||||
| 
 | ||||
| 	client.miner().import_own_transaction(&**client, tx0).unwrap(); | ||||
| 	client.miner().import_own_transaction(&**client, tx1).unwrap(); | ||||
| 	assert_eq!(0, client.ready_transactions().len()); | ||||
| 	assert_eq!(2, client.miner().pending_transactions().len()); | ||||
| 	push_blocks_to_client(client, 53, 2, 2); | ||||
| 	client.flush_queue(); | ||||
| 	assert_eq!(2, client.ready_transactions().len()); | ||||
| 	assert_eq!(2, client.miner().pending_transactions().len()); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -390,6 +390,34 @@ impl Deref for LocalizedTransaction { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /// Queued transaction with additional information.
 | ||||
| #[derive(Debug, Clone, PartialEq, Eq, Binary)] | ||||
| pub struct PendingTransaction { | ||||
| 	/// Signed transaction data.
 | ||||
| 	pub transaction: SignedTransaction, | ||||
| 	/// To be activated at this block. `None` for immediately.
 | ||||
| 	pub min_block: Option<BlockNumber>, | ||||
| } | ||||
| 
 | ||||
| impl PendingTransaction { | ||||
| 	/// Create a new pending transaction from signed transaction.
 | ||||
| 	pub fn new(signed: SignedTransaction, min_block: Option<BlockNumber>) -> Self { | ||||
| 		PendingTransaction { | ||||
| 			transaction: signed, | ||||
| 			min_block: min_block, | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| impl From<SignedTransaction> for PendingTransaction { | ||||
| 	fn from(t: SignedTransaction) -> Self { | ||||
| 		PendingTransaction { | ||||
| 			transaction: t, | ||||
| 			min_block: None, | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn sender_test() { | ||||
| 	let t: SignedTransaction = decode(&::rustc_serialize::hex::FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap()); | ||||
|  | ||||
| @ -38,7 +38,7 @@ export default class SecureApi extends Api { | ||||
| 
 | ||||
|   setToken = () => { | ||||
|     window.localStorage.setItem('sysuiToken', this._transport.token); | ||||
|     console.log('SecureApi:setToken', this._transport.token); | ||||
|     // DEBUG: console.log('SecureApi:setToken', this._transport.token);
 | ||||
|   } | ||||
| 
 | ||||
|   _checkNodeUp () { | ||||
| @ -149,14 +149,14 @@ export default class SecureApi extends Api { | ||||
|         this._signerPort = signerPort.toNumber(); | ||||
|       }); | ||||
| 
 | ||||
|     console.log('SecureApi:connectSuccess', this._transport.token); | ||||
|     // DEBUG: console.log('SecureApi:connectSuccess', this._transport.token);
 | ||||
|   } | ||||
| 
 | ||||
|   updateToken (token, connectState = 0) { | ||||
|     this._connectState = connectState; | ||||
|     this._transport.updateToken(token.replace(/[^a-zA-Z0-9]/g, '')); | ||||
|     this._followConnection(); | ||||
|     console.log('SecureApi:updateToken', this._transport.token, connectState); | ||||
|     // DEBUG: console.log('SecureApi:updateToken', this._transport.token, connectState);
 | ||||
|   } | ||||
| 
 | ||||
|   get dappsPort () { | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>CFBundlePackageType</key><string>APPL</string><key>CFBundleInfoDictionaryVersion</key><string>6.0</string> | ||||
| <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>CFBundleIconFiles</key><string>Parity.png</string><key>CFBundlePackageType</key><string>APPL</string><key>CFBundleInfoDictionaryVersion</key><string>6.0</string> | ||||
| 
 | ||||
|     <key>CFBundleName</key>                      <string>Parity Ethereum</string> | ||||
|     <key>CFBundleExecutable</key>                <string>go.sh</string> | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								mac/Parity Ethereum.app/Contents/Parity.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								mac/Parity Ethereum.app/Contents/Parity.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 106 KiB | 
| @ -145,7 +145,7 @@ macro_rules! usage { | ||||
| 				} | ||||
| 
 | ||||
| 				let config_file = raw_args.flag_config.clone().unwrap_or_else(|| raw_args.clone().into_args(Config::default()).flag_config); | ||||
| 				let config_file = replace_home("", &config_file); | ||||
| 				let config_file = replace_home(&::dir::default_data_path(), &config_file); | ||||
| 				let config = match (fs::File::open(&config_file), raw_args.flag_config.is_some()) { | ||||
| 					// Load config file
 | ||||
| 					(Ok(mut file), _) => { | ||||
|  | ||||
| @ -21,6 +21,16 @@ use util::journaldb::Algorithm; | ||||
| use helpers::replace_home; | ||||
| use app_dirs::{AppInfo, get_app_root, AppDataType}; | ||||
| 
 | ||||
| #[cfg(target_os = "macos")] const AUTHOR: &'static str = "Parity"; | ||||
| #[cfg(target_os = "macos")] const PRODUCT: &'static str = "io.parity.ethereum"; | ||||
| #[cfg(target_os = "macos")] const PRODUCT_HYPERVISOR: &'static str = "io.parity.ethereum-updates"; | ||||
| #[cfg(target_os = "windows")] const AUTHOR: &'static str = "Parity"; | ||||
| #[cfg(target_os = "windows")] const PRODUCT: &'static str = "Ethereum"; | ||||
| #[cfg(target_os = "windows")] const PRODUCT_HYPERVISOR: &'static str = "EthereumUpdates"; | ||||
| #[cfg(not(any(target_os = "windows", target_os = "macos")))] const AUTHOR: &'static str = "parity"; | ||||
| #[cfg(not(any(target_os = "windows", target_os = "macos")))] const PRODUCT: &'static str = "io.parity.ethereum"; | ||||
| #[cfg(not(any(target_os = "windows", target_os = "macos")))] const PRODUCT_HYPERVISOR: &'static str = "io.parity.ethereum-updates"; | ||||
| 
 | ||||
| // this const is irrelevent cause we do have migrations now,
 | ||||
| // but we still use it for backwards compatibility
 | ||||
| const LEGACY_CLIENT_DB_VER_STR: &'static str = "5.3"; | ||||
| @ -195,12 +205,12 @@ impl DatabaseDirectories { | ||||
| } | ||||
| 
 | ||||
| pub fn default_data_path() -> String { | ||||
| 	let app_info = AppInfo { name: "parity", author: "parity" }; | ||||
| 	let app_info = AppInfo { name: PRODUCT, author: AUTHOR }; | ||||
| 	get_app_root(AppDataType::UserData, &app_info).map(|p| p.to_string_lossy().into_owned()).unwrap_or_else(|_| "$HOME/.parity".to_owned()) | ||||
| } | ||||
| 
 | ||||
| pub fn default_hypervisor_path() -> String { | ||||
| 	let app_info = AppInfo { name: "parity-hypervisor", author: "parity" }; | ||||
| 	let app_info = AppInfo { name: PRODUCT_HYPERVISOR, author: AUTHOR }; | ||||
| 	get_app_root(AppDataType::UserData, &app_info).map(|p| p.to_string_lossy().into_owned()).unwrap_or_else(|_| "$HOME/.parity-hypervisor".to_owned()) | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -72,7 +72,7 @@ pub fn start(conf: Configuration, deps: Dependencies) -> Result<Option<SignerSer | ||||
| fn codes_path(path: String) -> PathBuf { | ||||
| 	let mut p = PathBuf::from(path); | ||||
| 	p.push(CODES_FILENAME); | ||||
| 	let _ = restrict_permissions_owner(&p); | ||||
| 	let _ = restrict_permissions_owner(&p, true, false); | ||||
| 	p | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -23,7 +23,7 @@ use util::bytes::ToPretty; | ||||
| use ethkey::Signature; | ||||
| use ethcore::miner::MinerService; | ||||
| use ethcore::client::MiningBlockChainClient; | ||||
| use ethcore::transaction::{Action, SignedTransaction, Transaction}; | ||||
| use ethcore::transaction::{Action, SignedTransaction, PendingTransaction, Transaction}; | ||||
| use ethcore::account_provider::AccountProvider; | ||||
| 
 | ||||
| use jsonrpc_core::Error; | ||||
| @ -147,9 +147,9 @@ fn decrypt(accounts: &AccountProvider, address: Address, msg: Bytes, password: S | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| pub fn dispatch_transaction<C, M>(client: &C, miner: &M, signed_transaction: SignedTransaction) -> Result<H256, Error> | ||||
| pub fn dispatch_transaction<C, M>(client: &C, miner: &M, signed_transaction: PendingTransaction) -> Result<H256, Error> | ||||
| 	where C: MiningBlockChainClient, M: MinerService { | ||||
| 	let hash = signed_transaction.hash(); | ||||
| 	let hash = signed_transaction.transaction.hash(); | ||||
| 
 | ||||
| 	miner.import_own_transaction(client, signed_transaction) | ||||
| 		.map_err(errors::from_transaction_error) | ||||
| @ -190,6 +190,7 @@ pub fn sign_and_dispatch<C, M>(client: &C, miner: &M, accounts: &AccountProvider | ||||
| { | ||||
| 
 | ||||
| 	let network_id = client.signing_network_id(); | ||||
| 	let min_block = filled.min_block.clone(); | ||||
| 	let signed_transaction = try!(sign_no_dispatch(client, miner, accounts, filled, password)); | ||||
| 
 | ||||
| 	let (signed_transaction, token) = match signed_transaction { | ||||
| @ -198,7 +199,8 @@ pub fn sign_and_dispatch<C, M>(client: &C, miner: &M, accounts: &AccountProvider | ||||
| 	}; | ||||
| 
 | ||||
| 	trace!(target: "miner", "send_transaction: dispatching tx: {} for network ID {:?}", rlp::encode(&signed_transaction).to_vec().pretty(), network_id); | ||||
| 	dispatch_transaction(&*client, &*miner, signed_transaction).map(|hash| { | ||||
| 	let pending_transaction = PendingTransaction::new(signed_transaction, min_block); | ||||
| 	dispatch_transaction(&*client, &*miner, pending_transaction).map(|hash| { | ||||
| 		match token { | ||||
| 			Some(ref token) => WithToken::Yes(hash, token.clone()), | ||||
| 			None => WithToken::No(hash), | ||||
| @ -217,6 +219,7 @@ pub fn fill_optional_fields<C, M>(request: TransactionRequest, client: &C, miner | ||||
| 		gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()), | ||||
| 		value: request.value.unwrap_or_else(|| 0.into()), | ||||
| 		data: request.data.unwrap_or_else(Vec::new), | ||||
| 		min_block: request.min_block, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -33,6 +33,8 @@ pub struct TransactionRequest { | ||||
| 	pub data: Option<Bytes>, | ||||
| 	/// Transaction's nonce
 | ||||
| 	pub nonce: Option<U256>, | ||||
| 	/// Delay until this block if specified.
 | ||||
| 	pub min_block: Option<u64>, | ||||
| } | ||||
| 
 | ||||
| /// Transaction request coming from RPC with default values filled in.
 | ||||
| @ -52,6 +54,8 @@ pub struct FilledTransactionRequest { | ||||
| 	pub data: Bytes, | ||||
| 	/// Transaction's nonce
 | ||||
| 	pub nonce: Option<U256>, | ||||
| 	/// Delay until this block if specified.
 | ||||
| 	pub min_block: Option<u64>, | ||||
| } | ||||
| 
 | ||||
| impl From<FilledTransactionRequest> for TransactionRequest { | ||||
| @ -64,6 +68,7 @@ impl From<FilledTransactionRequest> for TransactionRequest { | ||||
| 			value: Some(r.value), | ||||
| 			data: Some(r.data), | ||||
| 			nonce: r.nonce, | ||||
| 			min_block: r.min_block, | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -328,6 +328,7 @@ mod test { | ||||
| 			value: 10_000_000.into(), | ||||
| 			data: vec![], | ||||
| 			nonce: None, | ||||
| 			min_block: None, | ||||
| 		}) | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -38,7 +38,7 @@ use ethcore::header::{Header as BlockHeader, BlockNumber as EthBlockNumber}; | ||||
| use ethcore::block::IsBlock; | ||||
| use ethcore::views::*; | ||||
| use ethcore::ethereum::Ethash; | ||||
| use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action}; | ||||
| use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, PendingTransaction, Action}; | ||||
| use ethcore::log_entry::LogEntry; | ||||
| use ethcore::filter::Filter as EthcoreFilter; | ||||
| use ethcore::snapshot::SnapshotService; | ||||
| @ -617,7 +617,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where | ||||
| 
 | ||||
| 		let raw_transaction = raw.to_vec(); | ||||
| 		match UntrustedRlp::new(&raw_transaction).as_val() { | ||||
| 			Ok(signed_transaction) => dispatch_transaction(&*take_weak!(self.client), &*take_weak!(self.miner), signed_transaction).map(Into::into), | ||||
| 			Ok(signed_transaction) => dispatch_transaction(&*take_weak!(self.client), &*take_weak!(self.miner), PendingTransaction::new(signed_transaction, None)).map(Into::into), | ||||
| 			Err(e) => Err(errors::from_rlp_error(e)), | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -270,7 +270,13 @@ impl<C, M, S: ?Sized, U> Parity for ParityClient<C, M, S, U> where | ||||
| 	fn pending_transactions(&self) -> Result<Vec<Transaction>, Error> { | ||||
| 		try!(self.active()); | ||||
| 
 | ||||
| 		Ok(take_weak!(self.miner).all_transactions().into_iter().map(Into::into).collect::<Vec<_>>()) | ||||
| 		Ok(take_weak!(self.miner).pending_transactions().into_iter().map(Into::into).collect::<Vec<_>>()) | ||||
| 	} | ||||
| 
 | ||||
| 	fn future_transactions(&self) -> Result<Vec<Transaction>, Error> { | ||||
| 		try!(self.active()); | ||||
| 
 | ||||
| 		Ok(take_weak!(self.miner).future_transactions().into_iter().map(Into::into).collect::<Vec<_>>()) | ||||
| 	} | ||||
| 
 | ||||
| 	fn pending_transactions_stats(&self) -> Result<BTreeMap<H256, TransactionStats>, Error> { | ||||
|  | ||||
| @ -21,7 +21,7 @@ use std::sync::{Arc, Weak}; | ||||
| use rlp::{UntrustedRlp, View}; | ||||
| use ethcore::account_provider::AccountProvider; | ||||
| use ethcore::client::MiningBlockChainClient; | ||||
| use ethcore::transaction::SignedTransaction; | ||||
| use ethcore::transaction::{SignedTransaction, PendingTransaction}; | ||||
| use ethcore::miner::MinerService; | ||||
| 
 | ||||
| use jsonrpc_core::Error; | ||||
| @ -82,6 +82,9 @@ impl<C: 'static, M: 'static> SignerClient<C, M> where C: MiningBlockChainClient, | ||||
| 				if let Some(gas) = modification.gas { | ||||
| 					request.gas = gas.into(); | ||||
| 				} | ||||
| 				if let Some(ref min_block) = modification.min_block { | ||||
| 					request.min_block = min_block.as_ref().and_then(|b| b.to_min_block_num()); | ||||
| 				} | ||||
| 			} | ||||
| 			let result = f(&*client, &*miner, &*accounts, payload); | ||||
| 			// Execute
 | ||||
| @ -155,7 +158,8 @@ impl<C: 'static, M: 'static> Signer for SignerClient<C, M> where C: MiningBlockC | ||||
| 
 | ||||
| 					// Dispatch if everything is ok
 | ||||
| 					if sender_matches && data_matches && value_matches && nonce_matches { | ||||
| 						dispatch_transaction(&*client, &*miner, signed_transaction) | ||||
| 						let pending_transaction = PendingTransaction::new(signed_transaction, request.min_block); | ||||
| 						dispatch_transaction(&*client, &*miner, pending_transaction) | ||||
| 							.map(Into::into) | ||||
| 							.map(ConfirmationResponse::SendTransaction) | ||||
| 					} else { | ||||
|  | ||||
| @ -22,7 +22,7 @@ use ethcore::error::{Error, CallError}; | ||||
| use ethcore::client::{MiningBlockChainClient, Executed, CallAnalytics}; | ||||
| use ethcore::block::{ClosedBlock, IsBlock}; | ||||
| use ethcore::header::BlockNumber; | ||||
| use ethcore::transaction::SignedTransaction; | ||||
| use ethcore::transaction::{SignedTransaction, PendingTransaction}; | ||||
| use ethcore::receipt::{Receipt, RichReceipt}; | ||||
| use ethcore::miner::{MinerService, MinerStatus, TransactionImportResult, LocalTransactionStatus}; | ||||
| use ethcore::account_provider::Error as AccountError; | ||||
| @ -160,17 +160,17 @@ impl MinerService for TestMinerService { | ||||
| 	} | ||||
| 
 | ||||
| 	/// Imports transactions to transaction queue.
 | ||||
| 	fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: SignedTransaction) -> | ||||
| 	fn import_own_transaction(&self, chain: &MiningBlockChainClient, pending: PendingTransaction) -> | ||||
| 		Result<TransactionImportResult, Error> { | ||||
| 
 | ||||
| 		// keep the pending nonces up to date
 | ||||
| 		if let Ok(ref sender) = transaction.sender() { | ||||
| 		if let Ok(ref sender) = pending.transaction.sender() { | ||||
| 			let nonce = self.last_nonce(sender).unwrap_or(chain.latest_nonce(sender)); | ||||
| 			self.last_nonces.write().insert(sender.clone(), nonce + U256::from(1)); | ||||
| 		} | ||||
| 
 | ||||
| 		// lets assume that all txs are valid
 | ||||
| 		self.imported_transactions.lock().push(transaction); | ||||
| 		self.imported_transactions.lock().push(pending.transaction); | ||||
| 
 | ||||
| 		Ok(TransactionImportResult::Current) | ||||
| 	} | ||||
| @ -204,16 +204,20 @@ impl MinerService for TestMinerService { | ||||
| 		self.pending_transactions.lock().get(hash).cloned() | ||||
| 	} | ||||
| 
 | ||||
| 	fn all_transactions(&self) -> Vec<SignedTransaction> { | ||||
| 		self.pending_transactions.lock().values().cloned().collect() | ||||
| 	fn pending_transactions(&self) -> Vec<PendingTransaction> { | ||||
| 		self.pending_transactions.lock().values().cloned().map(Into::into).collect() | ||||
| 	} | ||||
| 
 | ||||
| 	fn local_transactions(&self) -> BTreeMap<H256, LocalTransactionStatus> { | ||||
| 		self.local_transactions.lock().iter().map(|(hash, stats)| (*hash, stats.clone())).collect() | ||||
| 	} | ||||
| 
 | ||||
| 	fn pending_transactions(&self, _best_block: BlockNumber) -> Vec<SignedTransaction> { | ||||
| 		self.pending_transactions.lock().values().cloned().collect() | ||||
| 	fn ready_transactions(&self, _best_block: BlockNumber) -> Vec<PendingTransaction> { | ||||
| 		self.pending_transactions.lock().values().cloned().map(Into::into).collect() | ||||
| 	} | ||||
| 
 | ||||
| 	fn future_transactions(&self) -> Vec<PendingTransaction> { | ||||
| 		vec![] | ||||
| 	} | ||||
| 
 | ||||
| 	fn pending_receipt(&self, _best_block: BlockNumber, hash: &H256) -> Option<RichReceipt> { | ||||
|  | ||||
| @ -501,7 +501,7 @@ fn rpc_eth_pending_transaction_by_hash() { | ||||
| 		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","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 response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","minBlock":null,"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#"{
 | ||||
| 		"jsonrpc": "2.0", | ||||
| 		"method": "eth_getTransactionByHash", | ||||
| @ -817,6 +817,7 @@ fn rpc_eth_sign_transaction() { | ||||
| 		r#""gas":"0x76c0","gasPrice":"0x9184e72a000","# + | ||||
| 		&format!("\"hash\":\"0x{:?}\",", t.hash()) + | ||||
| 		r#""input":"0x","# + | ||||
| 		r#""minBlock":null,"# + | ||||
| 		&format!("\"networkId\":{},", t.network_id().map_or("null".to_owned(), |n| format!("{}", n))) + | ||||
| 		r#""nonce":"0x1","# + | ||||
| 		&format!("\"publicKey\":\"0x{:?}\",", t.public_key().unwrap()) + | ||||
|  | ||||
| @ -82,6 +82,7 @@ fn should_return_list_of_items_to_confirm() { | ||||
| 		value: U256::from(1), | ||||
| 		data: vec![], | ||||
| 		nonce: None, | ||||
| 		min_block: None, | ||||
| 	})).unwrap(); | ||||
| 	tester.signer.add_request(ConfirmationPayload::Signature(1.into(), 5.into())).unwrap(); | ||||
| 
 | ||||
| @ -89,7 +90,7 @@ fn should_return_list_of_items_to_confirm() { | ||||
| 	let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#; | ||||
| 	let response = concat!( | ||||
| 		r#"{"jsonrpc":"2.0","result":["#, | ||||
| 		r#"{"id":"0x1","payload":{"sendTransaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#, | ||||
| 		r#"{"id":"0x1","payload":{"sendTransaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","minBlock":null,"nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#, | ||||
| 		r#"{"id":"0x2","payload":{"sign":{"address":"0x0000000000000000000000000000000000000001","hash":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#, | ||||
| 		r#"],"id":1}"# | ||||
| 	); | ||||
| @ -111,6 +112,7 @@ fn should_reject_transaction_from_queue_without_dispatching() { | ||||
| 		value: U256::from(1), | ||||
| 		data: vec![], | ||||
| 		nonce: None, | ||||
| 		min_block: None, | ||||
| 	})).unwrap(); | ||||
| 	assert_eq!(tester.signer.requests().len(), 1); | ||||
| 
 | ||||
| @ -136,6 +138,7 @@ fn should_not_remove_transaction_if_password_is_invalid() { | ||||
| 		value: U256::from(1), | ||||
| 		data: vec![], | ||||
| 		nonce: None, | ||||
| 		min_block: None, | ||||
| 	})).unwrap(); | ||||
| 	assert_eq!(tester.signer.requests().len(), 1); | ||||
| 
 | ||||
| @ -178,6 +181,7 @@ fn should_confirm_transaction_and_dispatch() { | ||||
| 		value: U256::from(1), | ||||
| 		data: vec![], | ||||
| 		nonce: None, | ||||
| 		min_block: None, | ||||
| 	})).unwrap(); | ||||
| 
 | ||||
| 	let t = Transaction { | ||||
| @ -223,6 +227,7 @@ fn should_confirm_transaction_with_token() { | ||||
| 		value: U256::from(1), | ||||
| 		data: vec![], | ||||
| 		nonce: None, | ||||
| 		min_block: None, | ||||
| 	})).unwrap(); | ||||
| 
 | ||||
| 	let t = Transaction { | ||||
| @ -270,6 +275,7 @@ fn should_confirm_transaction_with_rlp() { | ||||
| 		value: U256::from(1), | ||||
| 		data: vec![], | ||||
| 		nonce: None, | ||||
| 		min_block: None, | ||||
| 	})).unwrap(); | ||||
| 
 | ||||
| 	let t = Transaction { | ||||
| @ -317,6 +323,7 @@ fn should_return_error_when_sender_does_not_match() { | ||||
| 		value: U256::from(1), | ||||
| 		data: vec![], | ||||
| 		nonce: None, | ||||
| 		min_block: None, | ||||
| 	})).unwrap(); | ||||
| 
 | ||||
| 	let t = Transaction { | ||||
|  | ||||
| @ -285,6 +285,7 @@ fn should_add_sign_transaction_to_the_queue() { | ||||
| 		r#""gas":"0x76c0","gasPrice":"0x9184e72a000","# + | ||||
| 		&format!("\"hash\":\"0x{:?}\",", t.hash()) + | ||||
| 		r#""input":"0x","# + | ||||
| 		r#""minBlock":null,"# + | ||||
| 		&format!("\"networkId\":{},", t.network_id().map_or("null".to_owned(), |n| format!("{}", n))) + | ||||
| 		r#""nonce":"0x1","# + | ||||
| 		&format!("\"publicKey\":\"0x{:?}\",", t.public_key().unwrap()) + | ||||
|  | ||||
| @ -123,6 +123,10 @@ build_rpc_trait! { | ||||
| 		#[rpc(name = "parity_pendingTransactions")] | ||||
| 		fn pending_transactions(&self) -> Result<Vec<Transaction>, Error>; | ||||
| 
 | ||||
| 		/// Returns all future transactions from transaction queue.
 | ||||
| 		#[rpc(name = "parity_futureTransactions")] | ||||
| 		fn future_transactions(&self) -> Result<Vec<Transaction>, Error>; | ||||
| 
 | ||||
| 		/// Returns propagation statistics on transactions pending in the queue.
 | ||||
| 		#[rpc(name = "parity_pendingTransactionsStats")] | ||||
| 		fn pending_transactions_stats(&self) -> Result<BTreeMap<H256, TransactionStats>, Error>; | ||||
|  | ||||
| @ -139,7 +139,7 @@ mod tests { | ||||
| 	fn test_serialize_block_transactions() { | ||||
| 		let t = BlockTransactions::Full(vec![Transaction::default()]); | ||||
| 		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,"networkId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0"}]"#); | ||||
| 		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","minBlock":null}]"#); | ||||
| 
 | ||||
| 		let t = BlockTransactions::Hashes(vec![H256::default().into()]); | ||||
| 		let serialized = serde_json::to_string(&t).unwrap(); | ||||
|  | ||||
| @ -14,12 +14,12 @@ | ||||
| // You should have received a copy of the GNU General Public License
 | ||||
| // along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
| 
 | ||||
| use serde::{Deserialize, Deserializer, Error}; | ||||
| use serde::{Deserialize, Deserializer, Error, Serialize, Serializer}; | ||||
| use serde::de::Visitor; | ||||
| use ethcore::client::BlockId; | ||||
| 
 | ||||
| /// Represents rpc api block number param.
 | ||||
| #[derive(Debug, PartialEq, Clone)] | ||||
| #[derive(Debug, PartialEq, Clone, Hash, Eq)] | ||||
| pub enum BlockNumber { | ||||
| 	/// Number
 | ||||
| 	Num(u64), | ||||
| @ -44,6 +44,27 @@ impl Deserialize for BlockNumber { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| impl BlockNumber { | ||||
| 	/// Convert block number to min block target.
 | ||||
| 	pub fn to_min_block_num(&self) -> Option<u64> { | ||||
| 		match *self { | ||||
| 			BlockNumber::Num(ref x) => Some(*x), | ||||
| 			_ => None, | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| impl Serialize for BlockNumber { | ||||
| 	fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { | ||||
| 		match *self { | ||||
| 			BlockNumber::Num(ref x) => serializer.serialize_str(&format!("0x{:x}", x)), | ||||
| 			BlockNumber::Latest => serializer.serialize_str("latest"), | ||||
| 			BlockNumber::Earliest => serializer.serialize_str("earliest"), | ||||
| 			BlockNumber::Pending => serializer.serialize_str("pending"), | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| struct BlockNumberVisitor; | ||||
| 
 | ||||
| impl Visitor for BlockNumberVisitor { | ||||
|  | ||||
| @ -20,7 +20,7 @@ use std::fmt; | ||||
| use serde::{Serialize, Serializer}; | ||||
| use util::log::Colour; | ||||
| 
 | ||||
| use v1::types::{U256, TransactionRequest, RichRawTransaction, H160, H256, H520, Bytes}; | ||||
| use v1::types::{U256, TransactionRequest, RichRawTransaction, H160, H256, H520, Bytes, BlockNumber}; | ||||
| use v1::helpers; | ||||
| 
 | ||||
| /// Confirmation waiting in a queue
 | ||||
| @ -193,6 +193,9 @@ pub struct TransactionModification { | ||||
| 	pub gas_price: Option<U256>, | ||||
| 	/// Modified gas
 | ||||
| 	pub gas: Option<U256>, | ||||
| 	/// Modified min block
 | ||||
| 	#[serde(rename="minBlock")] | ||||
| 	pub min_block: Option<Option<BlockNumber>>, | ||||
| } | ||||
| 
 | ||||
| /// Represents two possible return values.
 | ||||
| @ -234,7 +237,7 @@ impl<A, B> Serialize for Either<A, B>  where | ||||
| mod tests { | ||||
| 	use std::str::FromStr; | ||||
| 	use serde_json; | ||||
| 	use v1::types::{U256, H256}; | ||||
| 	use v1::types::{U256, H256, BlockNumber}; | ||||
| 	use v1::helpers; | ||||
| 	use super::*; | ||||
| 
 | ||||
| @ -267,12 +270,13 @@ mod tests { | ||||
| 				value: 100_000.into(), | ||||
| 				data: vec![1, 2, 3], | ||||
| 				nonce: Some(1.into()), | ||||
| 				min_block: None, | ||||
| 			}), | ||||
| 		}; | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let res = serde_json::to_string(&ConfirmationRequest::from(request)); | ||||
| 		let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#; | ||||
| 		let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","minBlock":null}}}"#; | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(res.unwrap(), expected.to_owned()); | ||||
| @ -291,12 +295,13 @@ mod tests { | ||||
| 				value: 100_000.into(), | ||||
| 				data: vec![1, 2, 3], | ||||
| 				nonce: Some(1.into()), | ||||
| 				min_block: None, | ||||
| 			}), | ||||
| 		}; | ||||
| 
 | ||||
| 		// when
 | ||||
| 		let res = serde_json::to_string(&ConfirmationRequest::from(request)); | ||||
| 		let expected = r#"{"id":"0xf","payload":{"signTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#; | ||||
| 		let expected = r#"{"id":"0xf","payload":{"signTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","minBlock":null}}}"#; | ||||
| 
 | ||||
| 		// then
 | ||||
| 		assert_eq!(res.unwrap(), expected.to_owned()); | ||||
| @ -324,7 +329,8 @@ mod tests { | ||||
| 	fn should_deserialize_modification() { | ||||
| 		// given
 | ||||
| 		let s1 = r#"{
 | ||||
| 			"gasPrice":"0xba43b7400" | ||||
| 			"gasPrice":"0xba43b7400", | ||||
| 			"minBlock":"0x42" | ||||
| 		}"#;
 | ||||
| 		let s2 = r#"{"gas": "0x1233"}"#; | ||||
| 		let s3 = r#"{}"#; | ||||
| @ -338,14 +344,17 @@ mod tests { | ||||
| 		assert_eq!(res1, TransactionModification { | ||||
| 			gas_price: Some(U256::from_str("0ba43b7400").unwrap()), | ||||
| 			gas: None, | ||||
| 			min_block: Some(Some(BlockNumber::Num(0x42))), | ||||
| 		}); | ||||
| 		assert_eq!(res2, TransactionModification { | ||||
| 			gas_price: None, | ||||
| 			gas: Some(U256::from_str("1233").unwrap()), | ||||
| 			min_block: None, | ||||
| 		}); | ||||
| 		assert_eq!(res3, TransactionModification { | ||||
| 			gas_price: None, | ||||
| 			gas: None, | ||||
| 			min_block: None, | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -17,9 +17,9 @@ | ||||
| use serde::{Serialize, Serializer}; | ||||
| use ethcore::miner; | ||||
| use ethcore::contract_address; | ||||
| use ethcore::transaction::{LocalizedTransaction, Action, SignedTransaction}; | ||||
| use ethcore::transaction::{LocalizedTransaction, Action, PendingTransaction, SignedTransaction}; | ||||
| use v1::helpers::errors; | ||||
| use v1::types::{Bytes, H160, H256, U256, H512}; | ||||
| use v1::types::{Bytes, H160, H256, U256, H512, BlockNumber}; | ||||
| 
 | ||||
| /// Transaction
 | ||||
| #[derive(Debug, Default, Clone, PartialEq, Serialize)] | ||||
| @ -69,6 +69,9 @@ pub struct Transaction { | ||||
| 	pub r: U256, | ||||
| 	/// The S field of the signature.
 | ||||
| 	pub s: U256, | ||||
| 	/// Transaction activates at specified block.
 | ||||
| 	#[serde(rename="minBlock")] | ||||
| 	pub min_block: Option<BlockNumber>, | ||||
| } | ||||
| 
 | ||||
| /// Local Transaction Status
 | ||||
| @ -187,6 +190,7 @@ impl From<LocalizedTransaction> for Transaction { | ||||
| 			v: t.original_v().into(), | ||||
| 			r: signature.r().into(), | ||||
| 			s: signature.s().into(), | ||||
| 			min_block: None, | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @ -220,10 +224,19 @@ impl From<SignedTransaction> for Transaction { | ||||
| 			v: t.original_v().into(), | ||||
| 			r: signature.r().into(), | ||||
| 			s: signature.s().into(), | ||||
| 			min_block: None, | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| impl From<PendingTransaction> for Transaction { | ||||
| 	fn from(t: PendingTransaction) -> Transaction { | ||||
| 		let mut r = Transaction::from(t.transaction); | ||||
| 		r.min_block = t.min_block.map(|b| BlockNumber::Num(b)); | ||||
| 		r | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| impl From<miner::LocalTransactionStatus> for LocalTransactionStatus { | ||||
| 	fn from(s: miner::LocalTransactionStatus) -> Self { | ||||
| 		use ethcore::miner::LocalTransactionStatus::*; | ||||
| @ -248,7 +261,7 @@ mod tests { | ||||
| 	fn test_transaction_serialize() { | ||||
| 		let t = Transaction::default(); | ||||
| 		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,"networkId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0"}"#); | ||||
| 		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","minBlock":null}"#); | ||||
| 	} | ||||
| 
 | ||||
| 	#[test] | ||||
|  | ||||
| @ -16,7 +16,7 @@ | ||||
| 
 | ||||
| //! `TransactionRequest` type
 | ||||
| 
 | ||||
| use v1::types::{Bytes, H160, U256}; | ||||
| use v1::types::{Bytes, H160, U256, BlockNumber}; | ||||
| use v1::helpers; | ||||
| use util::log::Colour; | ||||
| 
 | ||||
| @ -41,6 +41,9 @@ pub struct TransactionRequest { | ||||
| 	pub data: Option<Bytes>, | ||||
| 	/// Transaction's nonce
 | ||||
| 	pub nonce: Option<U256>, | ||||
| 	/// Delay until this block if specified.
 | ||||
| 	#[serde(rename="minBlock")] | ||||
| 	pub min_block: Option<BlockNumber>, | ||||
| } | ||||
| 
 | ||||
| pub fn format_ether(i: U256) -> String { | ||||
| @ -90,6 +93,7 @@ impl From<helpers::TransactionRequest> for TransactionRequest { | ||||
| 			value: r.value.map(Into::into), | ||||
| 			data: r.data.map(Into::into), | ||||
| 			nonce: r.nonce.map(Into::into), | ||||
| 			min_block: r.min_block.map(|b| BlockNumber::Num(b)), | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @ -104,6 +108,7 @@ impl From<helpers::FilledTransactionRequest> for TransactionRequest { | ||||
| 			value: Some(r.value.into()), | ||||
| 			data: Some(r.data.into()), | ||||
| 			nonce: r.nonce.map(Into::into), | ||||
| 			min_block: r.min_block.map(|b| BlockNumber::Num(b)), | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @ -118,6 +123,7 @@ impl Into<helpers::TransactionRequest> for TransactionRequest { | ||||
| 			value: self.value.map(Into::into), | ||||
| 			data: self.data.map(Into::into), | ||||
| 			nonce: self.nonce.map(Into::into), | ||||
| 			min_block: self.min_block.and_then(|b| b.to_min_block_num()), | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @ -128,7 +134,7 @@ mod tests { | ||||
| 	use std::str::FromStr; | ||||
| 	use rustc_serialize::hex::FromHex; | ||||
| 	use serde_json; | ||||
| 	use v1::types::{U256, H160}; | ||||
| 	use v1::types::{U256, H160, BlockNumber}; | ||||
| 	use super::*; | ||||
| 
 | ||||
| 	#[test] | ||||
| @ -140,7 +146,8 @@ mod tests { | ||||
| 			"gas":"0x2", | ||||
| 			"value":"0x3", | ||||
| 			"data":"0x123456", | ||||
| 			"nonce":"0x4" | ||||
| 			"nonce":"0x4", | ||||
| 			"minBlock":"0x13" | ||||
| 		}"#;
 | ||||
| 		let deserialized: TransactionRequest = serde_json::from_str(s).unwrap(); | ||||
| 
 | ||||
| @ -152,6 +159,7 @@ mod tests { | ||||
| 			value: Some(U256::from(3)), | ||||
| 			data: Some(vec![0x12, 0x34, 0x56].into()), | ||||
| 			nonce: Some(U256::from(4)), | ||||
| 			min_block: Some(BlockNumber::Num(0x13)), | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| @ -174,7 +182,8 @@ mod tests { | ||||
| 			gas: Some(U256::from_str("76c0").unwrap()), | ||||
| 			value: Some(U256::from_str("9184e72a").unwrap()), | ||||
| 			data: Some("d46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675".from_hex().unwrap().into()), | ||||
| 			nonce: None | ||||
| 			nonce: None, | ||||
| 			min_block: None, | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| @ -191,6 +200,7 @@ mod tests { | ||||
| 			value: None, | ||||
| 			data: None, | ||||
| 			nonce: None, | ||||
| 			min_block: None, | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| @ -214,6 +224,7 @@ mod tests { | ||||
| 			value: None, | ||||
| 			data: Some(vec![0x85, 0x95, 0xba, 0xb1].into()), | ||||
| 			nonce: None, | ||||
| 			min_block: None, | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -91,7 +91,7 @@ fn list_transactions(signer: &mut SignerRpc) -> Result<String, String> { | ||||
| fn sign_transaction( | ||||
| 	signer: &mut SignerRpc, id: U256, password: &str | ||||
| ) -> Result<String, String> { | ||||
| 	try!(signer.confirm_request(id, None, None, password).map(|res| { | ||||
| 	try!(signer.confirm_request(id, None, None, None, password).map(|res| { | ||||
| 		match res { | ||||
| 			Ok(u) => Ok(format!("Signed transaction id: {:#x}", u)), | ||||
| 			Err(e) => Err(format!("{:?}", e)), | ||||
|  | ||||
| @ -8,7 +8,6 @@ version = "1.4.0" | ||||
| 
 | ||||
| [dependencies] | ||||
| futures = "0.1" | ||||
| jsonrpc-core = "3.0.2" | ||||
| lazy_static = "0.2.1" | ||||
| log = "0.3.6" | ||||
| matches = "0.1.2" | ||||
| @ -17,6 +16,7 @@ serde = "0.8" | ||||
| serde_json = "0.8" | ||||
| tempdir = "0.3.5" | ||||
| url = "1.2.0" | ||||
| jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } | ||||
| ws = { git = "https://github.com/ethcore/ws-rs.git", branch = "mio-upstream-stable" } | ||||
| ethcore-rpc = { path = "../rpc" } | ||||
| ethcore-signer = { path = "../signer" } | ||||
|  | ||||
| @ -36,7 +36,7 @@ use futures::{BoxFuture, Canceled, Complete, Future, oneshot, done}; | ||||
| 
 | ||||
| use jsonrpc_core::{Id, Version, Params, Error as JsonRpcError}; | ||||
| use jsonrpc_core::request::MethodCall; | ||||
| use jsonrpc_core::response::{SyncOutput, Success, Failure}; | ||||
| use jsonrpc_core::response::{Output, Success, Failure}; | ||||
| 
 | ||||
| /// The actual websocket connection handler, passed into the
 | ||||
| /// event loop of ws-rs
 | ||||
| @ -107,13 +107,13 @@ impl Handler for RpcHandler { | ||||
| 		let ret: Result<JsonValue, JsonRpcError>; | ||||
| 		let response_id; | ||||
| 		let string = &msg.to_string(); | ||||
| 		match json::from_str::<SyncOutput>(&string) { | ||||
| 			Ok(SyncOutput::Success(Success { result, id: Id::Num(id), .. })) => | ||||
| 		match json::from_str::<Output>(&string) { | ||||
| 			Ok(Output::Success(Success { result, id: Id::Num(id), .. })) => | ||||
| 			{ | ||||
| 				ret = Ok(result); | ||||
| 				response_id = id as usize; | ||||
| 			} | ||||
| 			Ok(SyncOutput::Failure(Failure { error, id: Id::Num(id), .. })) => { | ||||
| 			Ok(Output::Failure(Failure { error, id: Id::Num(id), .. })) => { | ||||
| 				ret = Err(error); | ||||
| 				response_id = id as usize; | ||||
| 			} | ||||
|  | ||||
| @ -1,7 +1,5 @@ | ||||
| use client::{Rpc, RpcError}; | ||||
| use rpc::v1::types::{ConfirmationRequest, | ||||
| 					 TransactionModification, | ||||
| 					 U256}; | ||||
| use rpc::v1::types::{ConfirmationRequest, TransactionModification, U256, BlockNumber}; | ||||
| use serde_json::{Value as JsonValue, to_value}; | ||||
| use std::path::PathBuf; | ||||
| use futures::{BoxFuture, Canceled}; | ||||
| @ -24,12 +22,13 @@ impl SignerRpc { | ||||
| 		id: U256, | ||||
| 		new_gas: Option<U256>, | ||||
| 		new_gas_price: Option<U256>, | ||||
| 		new_min_block: Option<Option<BlockNumber>>, | ||||
| 		pwd: &str | ||||
| 	) -> BoxFuture<Result<U256, RpcError>, Canceled> | ||||
| 	{ | ||||
| 		self.rpc.request("signer_confirmRequest", vec![ | ||||
| 			to_value(&format!("{:#x}", id)), | ||||
| 			to_value(&TransactionModification { gas_price: new_gas_price, gas: new_gas }), | ||||
| 			to_value(&TransactionModification { gas_price: new_gas_price, gas: new_gas, min_block: new_min_block }), | ||||
| 			to_value(&pwd), | ||||
| 		]) | ||||
| 	} | ||||
|  | ||||
| @ -1919,15 +1919,15 @@ impl ChainSync { | ||||
| 			return 0; | ||||
| 		} | ||||
| 
 | ||||
| 		let transactions = io.chain().pending_transactions(); | ||||
| 		let transactions = io.chain().ready_transactions(); | ||||
| 		if transactions.is_empty() { | ||||
| 			return 0; | ||||
| 		} | ||||
| 
 | ||||
| 		let all_transactions_hashes = transactions.iter().map(|tx| tx.hash()).collect::<HashSet<H256>>(); | ||||
| 		let all_transactions_hashes = transactions.iter().map(|tx| tx.transaction.hash()).collect::<HashSet<H256>>(); | ||||
| 		let all_transactions_rlp = { | ||||
| 			let mut packet = RlpStream::new_list(transactions.len()); | ||||
| 			for tx in &transactions { packet.append(tx); } | ||||
| 			for tx in &transactions { packet.append(&tx.transaction); } | ||||
| 			packet.out() | ||||
| 		}; | ||||
| 
 | ||||
| @ -1965,11 +1965,11 @@ impl ChainSync { | ||||
| 					// Construct RLP
 | ||||
| 					let mut packet = RlpStream::new_list(to_send.len()); | ||||
| 					for tx in &transactions { | ||||
| 						if to_send.contains(&tx.hash()) { | ||||
| 							packet.append(tx); | ||||
| 						if to_send.contains(&tx.transaction.hash()) { | ||||
| 							packet.append(&tx.transaction); | ||||
| 							// update stats
 | ||||
| 							let id = io.peer_session_info(*peer_id).and_then(|info| info.id); | ||||
| 							stats.propagated(tx.hash(), id, block_number); | ||||
| 							stats.propagated(tx.transaction.hash(), id, block_number); | ||||
| 						} | ||||
| 					} | ||||
| 
 | ||||
|  | ||||
| @ -44,15 +44,16 @@ impl IoHandler<ClientIoMessage> for TestIoHandler { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn new_tx(secret: &H256, nonce: U256) -> SignedTransaction { | ||||
| 	Transaction { | ||||
| fn new_tx(secret: &H256, nonce: U256) -> PendingTransaction { | ||||
| 	let signed = Transaction { | ||||
| 		nonce: nonce.into(), | ||||
| 		gas_price: 0.into(), | ||||
| 		gas: 21000.into(), | ||||
| 		action: Action::Call(Address::default()), | ||||
| 		value: 0.into(), | ||||
| 		data: Vec::new(), | ||||
| 	}.sign(secret, None) | ||||
| 	}.sign(secret, None); | ||||
| 	PendingTransaction::new(signed, None) | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
|  | ||||
| @ -18,6 +18,7 @@ ethcore-util = { path = "../util" } | ||||
| parity-hash-fetch = { path = "../hash-fetch" } | ||||
| ipc-common-types = { path = "../ipc-common-types" } | ||||
| ethcore-ipc = { path = "../ipc/rpc" } | ||||
| target_info = "0.1" | ||||
| 
 | ||||
| [profile.release] | ||||
| debug = true | ||||
|  | ||||
| @ -24,6 +24,7 @@ extern crate ethcore; | ||||
| extern crate ethabi; | ||||
| extern crate ethsync; | ||||
| extern crate ethcore_ipc as ipc; | ||||
| extern crate target_info; | ||||
| 
 | ||||
| mod updater; | ||||
| mod operations; | ||||
|  | ||||
| @ -18,8 +18,10 @@ use std::sync::{Arc, Weak}; | ||||
| use std::fs; | ||||
| use std::io::Write; | ||||
| use std::path::{PathBuf}; | ||||
| use util::misc::platform; | ||||
| use target_info::Target; | ||||
| use util::misc; | ||||
| use ipc_common_types::{VersionInfo, ReleaseTrack}; | ||||
| use util::path::restrict_permissions_owner; 
 | ||||
| use util::{Address, H160, H256, FixedHash, Mutex, Bytes}; | ||||
| use ethsync::{SyncProvider}; | ||||
| use ethcore::client::{BlockId, BlockChainClient, ChainNotify}; | ||||
| @ -97,6 +99,18 @@ pub struct Updater { | ||||
| 
 | ||||
| const CLIENT_ID: &'static str = "parity"; | ||||
| 
 | ||||
| fn platform() -> String { | ||||
| 	if cfg!(target_os = "macos") { | ||||
| 		"x86_64-apple-darwin".into() | ||||
| 	} else if cfg!(windows) { | ||||
| 		"x86_64-pc-windows-msvc".into() | ||||
| 	} else if cfg!(target_os = "linux") { | ||||
| 		format!("{}-unknown-linux-gnu", Target::arch()) | ||||
| 	} else { | ||||
| 		misc::platform() | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| impl Updater { | ||||
| 	pub fn new(client: Weak<BlockChainClient>, sync: Weak<SyncProvider>, update_policy: UpdatePolicy) -> Arc<Self> { | ||||
| 		let r = Arc::new(Updater { | ||||
| @ -197,7 +211,8 @@ impl Updater { | ||||
| 				let dest = self.updates_path(&Self::update_file_name(&fetched.version)); | ||||
| 				fs::create_dir_all(dest.parent().expect("at least one thing pushed; qed")).map_err(|e| format!("Unable to create updates path: {:?}", e))?; | ||||
| 				fs::copy(&b, &dest).map_err(|e| format!("Unable to copy update: {:?}", e))?; | ||||
| 				info!(target: "updater", "Copied file to {}", dest.display()); | ||||
| 				restrict_permissions_owner(&dest, false, true).map_err(|e| format!("Unable to update permissions: {}", e))?; | ||||
| 				info!(target: "updater", "Installed updated binary to {}", dest.display()); | ||||
| 				let auto = match self.update_policy.filter { | ||||
| 					UpdateFilter::All => true, | ||||
| 					UpdateFilter::Critical if fetched.is_critical /* TODO: or is on a bad fork */ => true, | ||||
| @ -241,7 +256,7 @@ impl Updater { | ||||
| 			trace!(target: "updater", "Latest release in our track is v{} it is {}critical ({} binary is {})", | ||||
| 				latest.track.version, | ||||
| 				if latest.track.is_critical {""} else {"non-"}, | ||||
| 				platform(), | ||||
| 				&platform(), | ||||
| 				if let Some(ref b) = latest.track.binary { | ||||
| 					format!("{}", b) | ||||
| 				} else { | ||||
|  | ||||
| @ -41,6 +41,7 @@ lru-cache = "0.1.0" | ||||
| [features] | ||||
| default = [] | ||||
| dev = ["clippy"] | ||||
| final = [] | ||||
| 
 | ||||
| [build-dependencies] | ||||
| vergen = "*" | ||||
|  | ||||
| @ -1168,8 +1168,8 @@ fn save_key(path: &Path, key: &Secret) { | ||||
| 			return; | ||||
| 		} | ||||
| 	}; | ||||
| 	if let Err(e) = restrict_permissions_owner(path) { | ||||
| 		warn!(target: "network", "Failed to modify permissions of the file (chmod: {})", e); | ||||
| 	if let Err(e) = restrict_permissions_owner(path, true, false) { | ||||
| 		warn!(target: "network", "Failed to modify permissions of the file ({})", e); | ||||
| 	} | ||||
| 	if let Err(e) = file.write(&key.hex().into_bytes()) { | ||||
| 		warn!("Error writing key file: {:?}", e); | ||||
|  | ||||
| @ -23,6 +23,14 @@ use target_info::Target; | ||||
| include!(concat!(env!("OUT_DIR"), "/version.rs")); | ||||
| include!(concat!(env!("OUT_DIR"), "/rustc_version.rs")); | ||||
| 
 | ||||
| #[cfg(feature = "final")] | ||||
| const THIS_TRACK: &'static str = "nightly"; 
 | ||||
| // ^^^ should be reset to "stable" or "beta" according to the release branch.
 | ||||
| 
 | ||||
| #[cfg(not(feature = "final"))] | ||||
| const THIS_TRACK: &'static str = "unstable"; | ||||
| // ^^^ This gets used when we're not building a final release; should stay as "unstable".
 | ||||
| 
 | ||||
| /// Boolean type for clean/dirty status.
 | ||||
| #[derive(PartialEq, Eq, Clone, Copy, Debug)] | ||||
| pub enum Filth { | ||||
| @ -45,7 +53,7 @@ pub fn version() -> String { | ||||
| 	let sha3_dash = if sha3.is_empty() { "" } else { "-" }; | ||||
| 	let commit_date = commit_date().replace("-", ""); | ||||
| 	let date_dash = if commit_date.is_empty() { "" } else { "-" }; | ||||
| 	format!("Parity/v{}-unstable{}{}{}{}/{}/rustc{}", env!("CARGO_PKG_VERSION"), sha3_dash, sha3, date_dash, commit_date, platform(), rustc_version()) | ||||
| 	format!("Parity/v{}-{}{}{}{}{}/{}/rustc{}", env!("CARGO_PKG_VERSION"), THIS_TRACK, sha3_dash, sha3, date_dash, commit_date, platform(), rustc_version()) | ||||
| } | ||||
| 
 | ||||
| /// Get the standard version data for this software.
 | ||||
| @ -64,5 +72,5 @@ pub fn version_data() -> Bytes { | ||||
| 
 | ||||
| /// Provide raw information on the package.
 | ||||
| pub fn raw_package_info() -> (&'static str, &'static str, &'static str) { | ||||
| 	(env!["CARGO_PKG_VERSION_PRE"], env!["CARGO_PKG_VERSION"], sha()) | ||||
| 	(THIS_TRACK, env!["CARGO_PKG_VERSION"], sha()) | ||||
| } | ||||
| @ -86,18 +86,15 @@ pub mod ethereum { | ||||
| } | ||||
| 
 | ||||
| /// Restricts the permissions of given path only to the owner.
 | ||||
| #[cfg(not(windows))] | ||||
| pub fn restrict_permissions_owner(file_path: &Path) -> Result<(), i32>  { | ||||
| 	let cstr = ::std::ffi::CString::new(file_path.to_str().unwrap()).unwrap(); | ||||
| 	match unsafe { ::libc::chmod(cstr.as_ptr(), ::libc::S_IWUSR | ::libc::S_IRUSR) } { | ||||
| 		0 => Ok(()), | ||||
| 		x => Err(x), | ||||
| 	} | ||||
| #[cfg(unix)] | ||||
| pub fn restrict_permissions_owner(file_path: &Path, write: bool, executable: bool) -> Result<(), String>  { | ||||
| 	let perms = ::std::os::unix::fs::PermissionsExt::from_mode(0o400 + write as u32 * 0o200 + executable as u32 * 0o100); | ||||
| 	::std::fs::set_permissions(file_path, perms).map_err(|e| format!("{:?}", e)) | ||||
| } | ||||
| 
 | ||||
| /// Restricts the permissions of given path only to the owner.
 | ||||
| #[cfg(windows)] | ||||
| pub fn restrict_permissions_owner(_file_path: &Path) -> Result<(), i32>  { | ||||
| #[cfg(not(unix))] | ||||
| pub fn restrict_permissions_owner(_file_path: &Path, _write: bool, _executable: bool) -> Result<(), String>  { | ||||
| 	//TODO: implement me
 | ||||
| 	Ok(()) | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user