Use Geth for contract tests
This commit is contained in:
parent
da3f783a9f
commit
577156fe5f
@ -200,7 +200,8 @@ export class ZeroEx {
|
|||||||
*/
|
*/
|
||||||
public async awaitTransactionMinedAsync(
|
public async awaitTransactionMinedAsync(
|
||||||
txHash: string,
|
txHash: string,
|
||||||
pollingIntervalMs: number = 1000,
|
// TODO(albrow): Change this back to 1000
|
||||||
|
pollingIntervalMs: number = 100,
|
||||||
timeoutMs?: number,
|
timeoutMs?: number,
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
// Hack: Get Web3Wrapper from ContractWrappers
|
// Hack: Get Web3Wrapper from ContractWrappers
|
||||||
|
20
packages/contracts/test/utils/assertions.ts
Normal file
20
packages/contracts/test/utils/assertions.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import * as chai from 'chai';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { constants } from '../../util/constants';
|
||||||
|
|
||||||
|
const expect = chai.expect;
|
||||||
|
|
||||||
|
// throws if the given promise does not reject with one of two expected error
|
||||||
|
// messages.
|
||||||
|
export const expectRevertOrAlwaysFailingTransaction = <T>(p: Promise<T>) => {
|
||||||
|
return expect(p)
|
||||||
|
.to.be.rejected()
|
||||||
|
.then(e => {
|
||||||
|
expect(e).to.satisfy(
|
||||||
|
(err: Error) =>
|
||||||
|
_.includes(err.message, constants.REVERT) ||
|
||||||
|
_.includes(err.message, constants.ALWAYS_FAILING_TRANSACTION),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
@ -1,6 +1,17 @@
|
|||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
|
import * as _ from 'lodash';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
enum NodeType {
|
||||||
|
Geth = 'GETH',
|
||||||
|
Ganache = 'GANACHE',
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are unique identifiers contained in the response of the
|
||||||
|
// web3_clientVersion call.
|
||||||
|
const GETH_VERSION_ID = 'Geth';
|
||||||
|
const GANACHE_VERSION_ID = 'EthereumJS TestRPC';
|
||||||
|
|
||||||
export class BlockchainLifecycle {
|
export class BlockchainLifecycle {
|
||||||
private _web3Wrapper: Web3Wrapper;
|
private _web3Wrapper: Web3Wrapper;
|
||||||
private _snapshotIdsStack: number[];
|
private _snapshotIdsStack: number[];
|
||||||
@ -8,17 +19,47 @@ export class BlockchainLifecycle {
|
|||||||
this._web3Wrapper = web3Wrapper;
|
this._web3Wrapper = web3Wrapper;
|
||||||
this._snapshotIdsStack = [];
|
this._snapshotIdsStack = [];
|
||||||
}
|
}
|
||||||
// TODO: In order to run these tests on an actual node, we should check if we are running against
|
|
||||||
// TestRPC, if so, use snapshots, otherwise re-deploy contracts before every test
|
|
||||||
public async startAsync(): Promise<void> {
|
public async startAsync(): Promise<void> {
|
||||||
const snapshotId = await this._web3Wrapper.takeSnapshotAsync();
|
const nodeType = await this._getNodeTypeAsync();
|
||||||
this._snapshotIdsStack.push(snapshotId);
|
switch (nodeType) {
|
||||||
|
case NodeType.Ganache:
|
||||||
|
const snapshotId = await this._web3Wrapper.takeSnapshotAsync();
|
||||||
|
this._snapshotIdsStack.push(snapshotId);
|
||||||
|
break;
|
||||||
|
case NodeType.Geth:
|
||||||
|
const blockNumber = await this._web3Wrapper.getBlockNumberAsync();
|
||||||
|
this._snapshotIdsStack.push(blockNumber);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown node type: ${nodeType}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public async revertAsync(): Promise<void> {
|
public async revertAsync(): Promise<void> {
|
||||||
const snapshotId = this._snapshotIdsStack.pop() as number;
|
const nodeType = await this._getNodeTypeAsync();
|
||||||
const didRevert = await this._web3Wrapper.revertSnapshotAsync(snapshotId);
|
switch (nodeType) {
|
||||||
if (!didRevert) {
|
case NodeType.Ganache:
|
||||||
throw new Error(`Snapshot with id #${snapshotId} failed to revert`);
|
const snapshotId = this._snapshotIdsStack.pop() as number;
|
||||||
|
const didRevert = await this._web3Wrapper.revertSnapshotAsync(snapshotId);
|
||||||
|
if (!didRevert) {
|
||||||
|
throw new Error(`Snapshot with id #${snapshotId} failed to revert`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NodeType.Geth:
|
||||||
|
const blockNumber = this._snapshotIdsStack.pop() as number;
|
||||||
|
await this._web3Wrapper.setHeadAsync(blockNumber);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown node type: ${nodeType}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private async _getNodeTypeAsync(): Promise<NodeType> {
|
||||||
|
const version = await this._web3Wrapper.getNodeVersionAsync();
|
||||||
|
if (_.includes(version, GETH_VERSION_ID)) {
|
||||||
|
return NodeType.Geth;
|
||||||
|
} else if (_.includes(version, GANACHE_VERSION_ID)) {
|
||||||
|
return NodeType.Ganache;
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unknown client version: ${version}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ export const web3Factory = {
|
|||||||
if (!hasAddresses) {
|
if (!hasAddresses) {
|
||||||
provider.addProvider(new EmptyWalletSubprovider());
|
provider.addProvider(new EmptyWalletSubprovider());
|
||||||
}
|
}
|
||||||
provider.addProvider(new FakeGasEstimateSubprovider(constants.GAS_LIMIT));
|
// provider.addProvider(new FakeGasEstimateSubprovider(constants.GAS_LIMIT));
|
||||||
const logger = {
|
const logger = {
|
||||||
log: (arg: any) => {
|
log: (arg: any) => {
|
||||||
fs.appendFileSync('ganache.log', `${arg}\n`);
|
fs.appendFileSync('ganache.log', `${arg}\n`);
|
||||||
|
29
packages/devnet/Dockerfile
Normal file
29
packages/devnet/Dockerfile
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
FROM alpine:3.7
|
||||||
|
|
||||||
|
RUN \
|
||||||
|
apk add --update go git make gcc musl-dev linux-headers ca-certificates && \
|
||||||
|
# TODO(albrow): Change the Git URL and branch once we have all relvant PRs
|
||||||
|
# merged to upstream.
|
||||||
|
git clone --depth 1 --branch sethead-txpool-fix https://github.com/0xProject/go-ethereum && \
|
||||||
|
(cd go-ethereum && make geth) && \
|
||||||
|
cp go-ethereum/build/bin/geth /geth && \
|
||||||
|
apk del go git make gcc musl-dev linux-headers && \
|
||||||
|
rm -rf /go-ethereum && rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
|
RUN mkdir ~/devnet
|
||||||
|
WORKDIR ~/devnet
|
||||||
|
|
||||||
|
COPY genesis.json .
|
||||||
|
COPY node0/ ./node0
|
||||||
|
COPY run.sh .
|
||||||
|
|
||||||
|
RUN /geth --datadir node0/ init genesis.json
|
||||||
|
|
||||||
|
EXPOSE 8501
|
||||||
|
EXPOSE 30310
|
||||||
|
|
||||||
|
ENTRYPOINT ./run.sh
|
||||||
|
|
||||||
|
# TODO(albrow): Send a single transaction to increment the block number from 0
|
||||||
|
# to 1. This seems to prevent bugs in the tests. (There's probably something
|
||||||
|
# Geth doesn't like about getting reset back to block 0).
|
75
packages/devnet/README.md
Normal file
75
packages/devnet/README.md
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
## 0x Devnet
|
||||||
|
|
||||||
|
A private, single-node PoA Ethereum network for testing purposes only. It uses
|
||||||
|
Geth and the PoA implementation called "Clique".
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
The devnet requires Docker to run (the latest version is recommended).
|
||||||
|
|
||||||
|
In the package root directory, run:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker build -t 0x-devnet .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
To start the network, run:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run -it --rm -p 8501:8501 0x-devnet
|
||||||
|
```
|
||||||
|
|
||||||
|
Depending on your OS and how you installed docker, you may need to prefix any
|
||||||
|
docker commands with `sudo`.
|
||||||
|
|
||||||
|
The Docker container exposes the JSON RPC API at port 8501, and this is the
|
||||||
|
primary way you are expected to interact with the devnet. The following
|
||||||
|
endpoints are supported: `personal,db,eth,net,web3,txpool,miner,debug`.
|
||||||
|
|
||||||
|
You can stop the network with `docker stop` and it will automatically clean up
|
||||||
|
after itself. (`docker stop` typically requires you to use `docker ps` to find
|
||||||
|
the name of the currently running container).
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
The devnet network only has a single node and using PoA instead of PoW. That
|
||||||
|
means that one node, called the "sealer", is the ultimate authority for
|
||||||
|
validating transactions and adding new blocks to the chain. Since there is no
|
||||||
|
PoW it also means that mining does not require significant computational
|
||||||
|
resources. You can learn more about PoA and the Geth-specific implementation
|
||||||
|
called "Clique" in [EIP-225](https://github.com/ethereum/EIPs/issues/225).
|
||||||
|
|
||||||
|
The address of the "sealer" is `0xe8816898d851d5b61b7f950627d04d794c07ca37`. The
|
||||||
|
password associated with the account is "password" and the (encrypted) private
|
||||||
|
keys are visible in the **node0/keystore** directory. This account is already
|
||||||
|
"unlocked" in the Geth node by default, so you can do things like sign and send
|
||||||
|
transactions from this account using the JSON RPC endpoints directly.
|
||||||
|
|
||||||
|
There are also a number of other addresses that have hard-coded starting
|
||||||
|
balances for testing purposes. You can see the details in the **genesis.json**
|
||||||
|
file. All of these accounts are also unlocked by default.
|
||||||
|
|
||||||
|
### Mining
|
||||||
|
|
||||||
|
The node will automatically (nearly instantly) mine a block whenever new
|
||||||
|
transactions are added to the transaction pool. If there are no transactions in
|
||||||
|
the pool, it will wait.
|
||||||
|
|
||||||
|
To stop mining, use the
|
||||||
|
[`miner.stop`](https://github.com/ethereum/go-ethereum/wiki/Management-APIs#miner_stop)
|
||||||
|
method.
|
||||||
|
|
||||||
|
To start mining again, you can use the
|
||||||
|
[`miner.start`](https://github.com/ethereum/go-ethereum/wiki/Management-APIs#miner_start)
|
||||||
|
JSON RPC method.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
We strongly recommend that the community help us make improvements and determine
|
||||||
|
the future direction of the protocol. To report bugs within this package, please
|
||||||
|
create an issue in this repository.
|
||||||
|
|
||||||
|
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting
|
||||||
|
started.
|
61
packages/devnet/genesis.json
Normal file
61
packages/devnet/genesis.json
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"chainId": 50,
|
||||||
|
"homesteadBlock": 1,
|
||||||
|
"eip150Block": 2,
|
||||||
|
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"eip155Block": 3,
|
||||||
|
"eip158Block": 3,
|
||||||
|
"byzantiumBlock": 4,
|
||||||
|
"clique": {
|
||||||
|
"period": 0,
|
||||||
|
"epoch": 30000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nonce": "0x0",
|
||||||
|
"timestamp": "0x5af1ffac",
|
||||||
|
"extraData":
|
||||||
|
"0x0000000000000000000000000000000000000000000000000000000000000000e8816898d851d5b61b7f950627d04d794c07ca370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"gasLimit": "0x47b760",
|
||||||
|
"difficulty": "0x1",
|
||||||
|
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"coinbase": "0x0000000000000000000000000000000000000000",
|
||||||
|
"alloc": {
|
||||||
|
"0xe8816898d851d5b61b7f950627d04d794c07ca37": {
|
||||||
|
"balance": "0x56BC75E2D63100000"
|
||||||
|
},
|
||||||
|
"0x5409ed021d9299bf6814279a6a1411a7e866a631": {
|
||||||
|
"balance": "0x56BC75E2D63100000"
|
||||||
|
},
|
||||||
|
"0x6ecbe1db9ef729cbe972c83fb886247691fb6beb": {
|
||||||
|
"balance": "0x56BC75E2D63100000"
|
||||||
|
},
|
||||||
|
"0xe36ea790bc9d7ab70c55260c66d52b1eca985f84": {
|
||||||
|
"balance": "0x56BC75E2D63100000"
|
||||||
|
},
|
||||||
|
"0xe834ec434daba538cd1b9fe1582052b880bd7e63": {
|
||||||
|
"balance": "0x56BC75E2D63100000"
|
||||||
|
},
|
||||||
|
"0x78dc5d2d739606d31509c31d654056a45185ecb6": {
|
||||||
|
"balance": "0x56BC75E2D63100000"
|
||||||
|
},
|
||||||
|
"0xa8dda8d7f5310e4a9e24f8eba77e091ac264f872": {
|
||||||
|
"balance": "0x56BC75E2D63100000"
|
||||||
|
},
|
||||||
|
"0x06cef8e666768cc40cc78cf93d9611019ddcb628": {
|
||||||
|
"balance": "0x56BC75E2D63100000"
|
||||||
|
},
|
||||||
|
"0x4404ac8bd8f9618d27ad2f1485aa1b2cfd82482d": {
|
||||||
|
"balance": "0x56BC75E2D63100000"
|
||||||
|
},
|
||||||
|
"0x7457d5e02197480db681d3fdf256c7aca21bdc12": {
|
||||||
|
"balance": "0x56BC75E2D63100000"
|
||||||
|
},
|
||||||
|
"0x91c987bf62d25945db517bdaa840a6c661374402": {
|
||||||
|
"balance": "0x56BC75E2D63100000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"number": "0x0",
|
||||||
|
"gasUsed": "0x0",
|
||||||
|
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
{"address":"5409ed021d9299bf6814279a6a1411a7e866a631","crypto":{"cipher":"aes-128-ctr","ciphertext":"7c7bdd62b303eb3a42d5d8e935825ed5a05a47cb2cef71e346c61b1bd582f1aa","cipherparams":{"iv":"7fd6c9d9f9893f2c480735b5386b6d75"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"79cc86edc3a668845a68fabb3913710b7504922e47aac8513ab3d6a28d090218"},"mac":"8a593ae0d0b964e47625bc964b6d389f5687f5bde631b4913136db4ab1b8083e"},"id":"29f637ba-6a65-4401-a0d1-30e1554bd776","version":3}
|
@ -0,0 +1 @@
|
|||||||
|
{"address":"6ecbe1db9ef729cbe972c83fb886247691fb6beb","crypto":{"cipher":"aes-128-ctr","ciphertext":"ecaf4f2839d74d92e2cb87c2fc7d52862661b46e697d70acfbe43f0893db73ed","cipherparams":{"iv":"7641c3a107228f8a901c07a07ea1f70d"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"c67c9fb30648df6985c0490b6603382147e7dc1ea28ca8c934af4a453ec0555b"},"mac":"985dca9ce65ad400fa4c9009742be2d409f402fe05203fc1278cfd1451729e8d"},"id":"e8634edc-08e6-415e-8d65-7985c4c4a05c","version":3}
|
@ -0,0 +1 @@
|
|||||||
|
{"address":"e36ea790bc9d7ab70c55260c66d52b1eca985f84","crypto":{"cipher":"aes-128-ctr","ciphertext":"49f89d7d612049f5f3581fc7c97d32ec9c9a2ca3c11165587139f16bfb29de6b","cipherparams":{"iv":"9767e0687a097c5b57e9cb30eec9bc0a"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"3e8f23332df99d519b602a0f6f4724338ba3fd9e7e313c337a92ffd1cafa19f1"},"mac":"4892051a669d45bb7de32a5eab63ee8fe52485a02218ce1806515da2adbd6584"},"id":"3488ad36-4a9d-4282-8651-7939b822429d","version":3}
|
@ -0,0 +1 @@
|
|||||||
|
{"address":"e834ec434daba538cd1b9fe1582052b880bd7e63","crypto":{"cipher":"aes-128-ctr","ciphertext":"a8ae3896739c63fc3bfe034277f6a1924a1c0ddc3f6747391dada8e61e15a928","cipherparams":{"iv":"f4f4d786cd3650a428a8bac5a6c824b1"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"9acecc321bcab9b69ffdea494b8894ad0221c30f05c17d2302e315db8708ecc6"},"mac":"fc416b8f539fdc1e39e87a3bd2a69b04455875de701ced60cc8948b222171380"},"id":"0d9703e8-14fc-45d0-a425-2c40b8ae846a","version":3}
|
@ -0,0 +1 @@
|
|||||||
|
{"address":"78dc5d2d739606d31509c31d654056a45185ecb6","crypto":{"cipher":"aes-128-ctr","ciphertext":"25e90e593f08e9e3adc426c8685d90db5d1c04957e9dc8d5fab4ae30c3306b61","cipherparams":{"iv":"72ece22297a27363e795b678bcbd6be5"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"2201502b9d3c4e2076d9d15bfd9da3a6c75d9e2e574aabb29c3bc5a3b5ec55a5"},"mac":"13d709ed4bd2f5bf4973fc1373f8434835f0d12dc99b32c6fc14d9df7f41c62d"},"id":"3902dff4-5681-4646-b825-849f96efeec5","version":3}
|
@ -0,0 +1 @@
|
|||||||
|
{"address":"a8dda8d7f5310e4a9e24f8eba77e091ac264f872","crypto":{"cipher":"aes-128-ctr","ciphertext":"0d67c13cf0b130e8ffa1aaca5df372f727164e633f8e0e28a3e54d0884ffb568","cipherparams":{"iv":"619cd539cda9f40abb45bba00b5fe53d"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"4effcd9b6fe71ee31cfe9057290154329b9af3acb6dcc46be7f78b5b9dcd3f42"},"mac":"c6eecd25944f4250b7b875d76bfbb60cc4e8db1d081621d1a2ddb72ea4e52a6d"},"id":"556bd3f1-1e5b-47a4-9b6e-448b9989d7d3","version":3}
|
@ -0,0 +1 @@
|
|||||||
|
{"address":"06cef8e666768cc40cc78cf93d9611019ddcb628","crypto":{"cipher":"aes-128-ctr","ciphertext":"38c9ca150932dc8c5ec5c65796425b2de98295cae64db08b816da2c06fc52c20","cipherparams":{"iv":"512127e8e606c481612473e7bc4d38f1"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"16c4cabfd13cae2df66d8ff9acc7f503c95c808b00d0bb6a12932203889c679b"},"mac":"52297b496e8751627dea1ee17bf5cbea1926f90bcde3ffc8baa089184672f875"},"id":"31102097-86e4-4e19-ad73-03c3de67bf3b","version":3}
|
@ -0,0 +1 @@
|
|||||||
|
{"address":"4404ac8bd8f9618d27ad2f1485aa1b2cfd82482d","crypto":{"cipher":"aes-128-ctr","ciphertext":"ca7aedbacc960fc0fcb418606d7bdf042c36cc2808a5c94ac222cc0b44a9970d","cipherparams":{"iv":"3b1fe5da1cf5d6cd2ceaaf24c008c897"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"a94e4d41d77ff6dc54beda30c7a46d8f3cc312ebeffa0352d679f7e3fc5301dc"},"mac":"9a82bf60103d05878f8af3c07765c22cba3df9b1c4376eaf859e47b805666e42"},"id":"ab68c67b-e15a-4ade-b3d9-2180a32b28fe","version":3}
|
@ -0,0 +1 @@
|
|||||||
|
{"address":"7457d5e02197480db681d3fdf256c7aca21bdc12","crypto":{"cipher":"aes-128-ctr","ciphertext":"720dcc2889c7b3636f9f659650181b0d46d82420460e23454277273f528baaee","cipherparams":{"iv":"1510028e2b9988d1a73b71cbb692d085"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"5db2b62f4d1f55a3f24c014c4f23f3ec9a2992dca6c2a89c24a566f99a079396"},"mac":"22c6fb134fd0a748195ea83e9ccb490ab2c9a3e8761f9d74ea6d02abbdeb8a43"},"id":"704c31f8-8ca2-4b49-9fdc-5923f5712dad","version":3}
|
@ -0,0 +1 @@
|
|||||||
|
{"address":"91c987bf62d25945db517bdaa840a6c661374402","crypto":{"cipher":"aes-128-ctr","ciphertext":"8f461f3c74643f382f7fc1f71719d5a89ed8cf75854d8a1b53e133997b53a386","cipherparams":{"iv":"cf595fb7680d36b4f5a01599ee54d2d1"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"73a9e599369d2bfaedd044559415147240c3517f6cd1dec8f77a98993d1ceaf8"},"mac":"c8be4dc59ad28d40f7b549a6b72834d149c84d67dc35e687676bbee0e07be395"},"id":"21cca6fb-7876-4e39-a986-a0a37f90da6d","version":3}
|
@ -0,0 +1 @@
|
|||||||
|
{"address":"e8816898d851d5b61b7f950627d04d794c07ca37","crypto":{"cipher":"aes-128-ctr","ciphertext":"1ff4add6955cba7ddaf29f66d7d21c5e1d714ef6191fbc651ae60f2ea3c95e8f","cipherparams":{"iv":"3ff869fbdbe1a523cdb327780365976e"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"7372dbae5fb318f8684902e099c311d4188721d677974d729711762c7ef6030c"},"mac":"485fa5dc701067782baa1589716a53110c7f917eb259e35ebca7265bbb7150b1"},"id":"89edb004-5b00-4607-a3af-a0d9ab9b1c34","version":3}
|
11
packages/devnet/node0/password.txt
Normal file
11
packages/devnet/node0/password.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
password
|
||||||
|
password
|
||||||
|
password
|
||||||
|
password
|
||||||
|
password
|
||||||
|
password
|
||||||
|
password
|
||||||
|
password
|
||||||
|
password
|
||||||
|
password
|
||||||
|
password
|
23
packages/devnet/run.sh
Executable file
23
packages/devnet/run.sh
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
set -e
|
||||||
|
|
||||||
|
# Create log directory for Geth
|
||||||
|
mkdir -p /var/log
|
||||||
|
|
||||||
|
# Start Geth in background and redirect output to log file
|
||||||
|
/geth --datadir node0/ --syncmode 'full' --nat none --nodiscover --port 30310 --txpool.journal '' \
|
||||||
|
--rpc --rpcaddr '0.0.0.0' --rpcport 8501 --rpcapi 'personal,db,eth,net,web3,txpool,miner,debug' \
|
||||||
|
--networkid 50 --gasprice '2000000000' --targetgaslimit '0x47b760' --mine --etherbase '0xe8816898d851d5b61b7f950627d04d794c07ca37' \
|
||||||
|
--unlock '0xe8816898d851d5b61b7f950627d04d794c07ca37,0x5409ed021d9299bf6814279a6a1411a7e866a631,0x6ecbe1db9ef729cbe972c83fb886247691fb6beb,0xe36ea790bc9d7ab70c55260c66d52b1eca985f84,0xe834ec434daba538cd1b9fe1582052b880bd7e63,0x78dc5d2d739606d31509c31d654056a45185ecb6,0xa8dda8d7f5310e4a9e24f8eba77e091ac264f872,0x06cef8e666768cc40cc78cf93d9611019ddcb628,0x4404ac8bd8f9618d27ad2f1485aa1b2cfd82482d,0x7457d5e02197480db681d3fdf256c7aca21bdc12,0x91c987bf62d25945db517bdaa840a6c661374402' \
|
||||||
|
--password=node0/password.txt \
|
||||||
|
> /var/log/geth &
|
||||||
|
|
||||||
|
# Wait for Geth to unlock the first account
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Send a single transaction. We have to do this so that debug.setHead works
|
||||||
|
# correctly. (Geth does not seem to like debug.setHead(0), so by sending this
|
||||||
|
# transaction we increase the current block number to 1).
|
||||||
|
/geth --datadir node0/ attach --exec 'eth.sendTransaction({"from": "0xe8816898d851d5b61b7f950627d04d794c07ca37", "to": "0x84bd1cfa409cb0bb9b23b8b1a33515b4ac00a0af", "value": "0x1"})'
|
||||||
|
|
||||||
|
# Use tail to re-attach to the log file and actually see the output.
|
||||||
|
tail -f /var/log/geth
|
@ -281,7 +281,6 @@ export class Web3Wrapper {
|
|||||||
};
|
};
|
||||||
const payload = {
|
const payload = {
|
||||||
jsonrpc: '2.0',
|
jsonrpc: '2.0',
|
||||||
id: this._jsonRpcRequestId++,
|
|
||||||
method: 'eth_getLogs',
|
method: 'eth_getLogs',
|
||||||
params: [serializedFilter],
|
params: [serializedFilter],
|
||||||
};
|
};
|
||||||
@ -403,8 +402,44 @@ export class Web3Wrapper {
|
|||||||
}
|
}
|
||||||
return receipt;
|
return receipt;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Start the CPU mining process with the given number of threads and
|
||||||
|
* generate a new DAG if need be.
|
||||||
|
* @param threads The number of threads to mine on.
|
||||||
|
*/
|
||||||
|
public async minerStartAsync(threads: number = 1): Promise<void> {
|
||||||
|
await this._sendRawPayloadAsync<boolean>({
|
||||||
|
method: 'miner_start',
|
||||||
|
params: [threads],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Stop the CPU mining process.
|
||||||
|
* @param threads The number of threads to mine on.
|
||||||
|
*/
|
||||||
|
public async minerStopAsync(): Promise<void> {
|
||||||
|
await this._sendRawPayloadAsync<boolean>({ method: 'miner_stop', params: [] });
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns true if client is actively mining new blocks.
|
||||||
|
* @returns A boolean indicating whether the node is currently mining.
|
||||||
|
*/
|
||||||
|
public async isMiningAsync(): Promise<boolean> {
|
||||||
|
const isMining = await promisify<boolean>(this._web3.eth.getMining)();
|
||||||
|
return isMining;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sets the current head of the local chain by block number. Note, this is a
|
||||||
|
* destructive action and may severely damage your chain. Use with extreme
|
||||||
|
* caution.
|
||||||
|
* @param blockNumber The block number to reset to.
|
||||||
|
*/
|
||||||
|
public async setHeadAsync(blockNumber: number): Promise<void> {
|
||||||
|
await this._sendRawPayloadAsync<void>({ method: 'debug_setHead', params: [this._web3.toHex(blockNumber)] });
|
||||||
|
}
|
||||||
private async _sendRawPayloadAsync<A>(payload: Partial<JSONRPCRequestPayload>): Promise<A> {
|
private async _sendRawPayloadAsync<A>(payload: Partial<JSONRPCRequestPayload>): Promise<A> {
|
||||||
const sendAsync = this._web3.currentProvider.sendAsync.bind(this._web3.currentProvider);
|
const sendAsync = this._web3.currentProvider.sendAsync.bind(this._web3.currentProvider);
|
||||||
|
payload.id = this._jsonRpcRequestId++;
|
||||||
const response = await promisify<JSONRPCResponsePayload>(sendAsync)(payload);
|
const response = await promisify<JSONRPCResponsePayload>(sendAsync)(payload);
|
||||||
const result = response.result;
|
const result = response.result;
|
||||||
return result;
|
return result;
|
||||||
|
@ -2,6 +2,7 @@ import * as chai from 'chai';
|
|||||||
import * as Ganache from 'ganache-core';
|
import * as Ganache from 'ganache-core';
|
||||||
import 'make-promises-safe';
|
import 'make-promises-safe';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
import { Web3Wrapper } from '../src';
|
import { Web3Wrapper } from '../src';
|
||||||
|
|
||||||
@ -37,4 +38,22 @@ describe('Web3Wrapper tests', () => {
|
|||||||
expect(networkId).to.be.equal(NETWORK_ID);
|
expect(networkId).to.be.equal(NETWORK_ID);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('mining functions', () => {
|
||||||
|
it('starts and stops the miner', async () => {
|
||||||
|
// Note: depending on our provider, the miner may or may not already
|
||||||
|
// be mining. To account for both conditions, we have what might
|
||||||
|
// look like too many stops and starts here, but it is necessary.
|
||||||
|
await web3Wrapper.minerStopAsync();
|
||||||
|
let isMining = await web3Wrapper.isMiningAsync();
|
||||||
|
expect(isMining).to.be.false();
|
||||||
|
await web3Wrapper.minerStartAsync(1);
|
||||||
|
isMining = await web3Wrapper.isMiningAsync();
|
||||||
|
expect(isMining).to.be.true();
|
||||||
|
isMining = await web3Wrapper.isMiningAsync();
|
||||||
|
expect(isMining).to.be.true();
|
||||||
|
await web3Wrapper.minerStopAsync();
|
||||||
|
isMining = await web3Wrapper.isMiningAsync();
|
||||||
|
expect(isMining).to.be.false();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user