2022-04-11 10:00:39 +00:00
|
|
|
import
|
|
|
|
std/[os, options, json, times, math],
|
|
|
|
eth/[common, keys],
|
|
|
|
eth/trie/db,
|
|
|
|
eth/p2p as eth_p2p,
|
|
|
|
stew/[results, byteutils],
|
|
|
|
stint,
|
|
|
|
json_rpc/[rpcserver, rpcclient],
|
|
|
|
../../../nimbus/[
|
|
|
|
config,
|
2022-06-17 00:53:33 +00:00
|
|
|
conf_utils,
|
2022-04-11 10:00:39 +00:00
|
|
|
genesis,
|
|
|
|
context,
|
|
|
|
constants,
|
|
|
|
transaction,
|
|
|
|
utils,
|
|
|
|
sealer,
|
|
|
|
p2p/chain,
|
|
|
|
db/db_chain,
|
|
|
|
rpc/p2p,
|
|
|
|
rpc/engine_api,
|
2022-06-14 06:04:12 +00:00
|
|
|
rpc/debug,
|
2022-07-18 04:34:42 +00:00
|
|
|
rpc/jwt_auth,
|
2022-05-13 16:30:10 +00:00
|
|
|
sync/protocol,
|
2022-11-14 07:32:33 +00:00
|
|
|
utils/tx_pool,
|
|
|
|
merge/merger
|
2022-04-11 10:00:39 +00:00
|
|
|
],
|
|
|
|
../../../tests/test_helpers,
|
|
|
|
"."/[clmock, engine_client]
|
|
|
|
|
|
|
|
import web3/engine_api_types
|
|
|
|
from web3/ethtypes as web3types import nil
|
|
|
|
|
|
|
|
export
|
|
|
|
common, engine_api_types, times,
|
|
|
|
options, results, constants, utils,
|
|
|
|
TypedTransaction, clmock, engine_client
|
|
|
|
|
|
|
|
type
|
|
|
|
EthBlockHeader* = common.BlockHeader
|
|
|
|
|
|
|
|
TestEnv* = ref object
|
2022-07-18 04:34:42 +00:00
|
|
|
conf*: NimbusConf
|
2022-04-11 10:00:39 +00:00
|
|
|
ctx: EthContext
|
|
|
|
ethNode: EthereumNode
|
|
|
|
chainDB: BaseChainDB
|
|
|
|
chainRef: Chain
|
2022-07-18 04:34:42 +00:00
|
|
|
rpcServer: RpcHttpServer
|
2022-04-11 10:00:39 +00:00
|
|
|
sealingEngine: SealingEngineRef
|
2022-07-18 04:34:42 +00:00
|
|
|
rpcClient*: RpcHttpClient
|
2022-04-11 10:00:39 +00:00
|
|
|
gHeader*: EthBlockHeader
|
|
|
|
ttd*: DifficultyInt
|
|
|
|
clMock*: CLMocker
|
2022-06-17 00:53:33 +00:00
|
|
|
nonce*: uint64
|
2022-06-13 09:42:01 +00:00
|
|
|
vaultKey*: PrivateKey
|
2022-06-17 00:53:33 +00:00
|
|
|
tx*: Transaction
|
2022-04-11 10:00:39 +00:00
|
|
|
|
|
|
|
Web3BlockHash* = web3types.BlockHash
|
|
|
|
Web3Address* = web3types.Address
|
|
|
|
Web3Bloom* = web3types.FixedBytes[256]
|
|
|
|
Web3Quantity* = web3types.Quantity
|
|
|
|
Web3PrevRandao* = web3types.FixedBytes[32]
|
|
|
|
Web3ExtraData* = web3types.DynamicBytes[0, 32]
|
|
|
|
|
|
|
|
const
|
|
|
|
baseFolder = "hive_integration" / "nodocker" / "engine"
|
|
|
|
genesisFile = baseFolder / "genesis.json"
|
|
|
|
sealerKey = baseFolder / "sealer.key"
|
2022-06-17 00:53:33 +00:00
|
|
|
chainFolder = baseFolder / "chains"
|
2022-04-11 10:00:39 +00:00
|
|
|
|
|
|
|
# This is the account that sends vault funding transactions.
|
|
|
|
vaultAccountAddr* = hexToByteArray[20]("0xcf49fda3be353c69b41ed96333cd24302da4556f")
|
|
|
|
vaultKeyHex = "63b508a03c3b5937ceb903af8b1b0c191012ef6eb7e9c3fb7afa94e5d214d376"
|
2022-07-18 04:34:42 +00:00
|
|
|
jwtSecret = "0x7365637265747365637265747365637265747365637265747365637265747365"
|
2022-04-11 10:00:39 +00:00
|
|
|
|
2022-07-18 04:34:42 +00:00
|
|
|
proc setupELClient*(t: TestEnv, chainFile: string, enableAuth: bool) =
|
2022-06-17 00:53:33 +00:00
|
|
|
if chainFile.len > 0:
|
|
|
|
# disable clique if we are using PoW chain
|
|
|
|
t.conf.networkParams.config.poaEngine = false
|
|
|
|
|
2022-04-11 10:00:39 +00:00
|
|
|
t.ctx = newEthContext()
|
|
|
|
let res = t.ctx.am.importPrivateKey(sealerKey)
|
|
|
|
if res.isErr:
|
|
|
|
echo res.error()
|
|
|
|
quit(QuitFailure)
|
|
|
|
|
|
|
|
t.ethNode = setupEthNode(t.conf, t.ctx, eth)
|
|
|
|
t.chainDB = newBaseChainDB(
|
|
|
|
newMemoryDb(),
|
|
|
|
t.conf.pruneMode == PruneMode.Full,
|
|
|
|
t.conf.networkId,
|
|
|
|
t.conf.networkParams
|
|
|
|
)
|
|
|
|
t.chainRef = newChain(t.chainDB)
|
|
|
|
|
|
|
|
initializeEmptyDb(t.chainDB)
|
|
|
|
let txPool = TxPoolRef.new(t.chainDB, t.conf.engineSigner)
|
|
|
|
|
2022-07-18 04:34:42 +00:00
|
|
|
var key: JwtSharedKey
|
|
|
|
let kr = key.fromHex(jwtSecret)
|
|
|
|
if kr.isErr:
|
|
|
|
echo "JWT SECRET ERROR: ", kr.error
|
|
|
|
quit(QuitFailure)
|
|
|
|
|
|
|
|
let hooks = if enableAuth:
|
|
|
|
@[httpJwtAuth(key)]
|
|
|
|
else:
|
|
|
|
@[]
|
|
|
|
|
|
|
|
t.rpcServer = newRpcHttpServer(["localhost:" & $t.conf.rpcPort], hooks)
|
2022-04-11 10:00:39 +00:00
|
|
|
t.sealingEngine = SealingEngineRef.new(
|
|
|
|
t.chainRef, t.ctx, t.conf.engineSigner,
|
|
|
|
txPool, EngineStopped
|
|
|
|
)
|
|
|
|
|
2022-11-14 07:32:33 +00:00
|
|
|
let merger = MergerRef.new(t.chainDB)
|
2022-04-11 10:00:39 +00:00
|
|
|
setupEthRpc(t.ethNode, t.ctx, t.chainDB, txPool, t.rpcServer)
|
2022-11-14 07:32:33 +00:00
|
|
|
setupEngineAPI(t.sealingEngine, t.rpcServer, merger)
|
2022-06-14 06:04:12 +00:00
|
|
|
setupDebugRpc(t.chainDB, t.rpcServer)
|
2022-04-11 10:00:39 +00:00
|
|
|
|
2022-06-17 00:53:33 +00:00
|
|
|
# Do not start clique sealing engine if we are using a Proof of Work chain file
|
|
|
|
if chainFile.len > 0:
|
|
|
|
if not importRlpBlock(chainFolder / chainFile, t.chainDB):
|
|
|
|
quit(QuitFailure)
|
2022-07-18 04:34:42 +00:00
|
|
|
elif not enableAuth:
|
2022-06-17 00:53:33 +00:00
|
|
|
t.sealingEngine.start()
|
|
|
|
|
2022-04-11 10:00:39 +00:00
|
|
|
t.rpcServer.start()
|
|
|
|
|
2022-07-18 04:34:42 +00:00
|
|
|
t.rpcClient = newRpcHttpClient()
|
|
|
|
waitFor t.rpcClient.connect("localhost", t.conf.rpcPort, false)
|
2022-04-11 10:00:39 +00:00
|
|
|
t.gHeader = toGenesisHeader(t.conf.networkParams)
|
|
|
|
|
|
|
|
let kRes = PrivateKey.fromHex(vaultKeyHex)
|
|
|
|
if kRes.isErr:
|
|
|
|
echo kRes.error
|
|
|
|
quit(QuitFailure)
|
|
|
|
|
|
|
|
t.vaultKey = kRes.get
|
|
|
|
|
2022-07-18 04:34:42 +00:00
|
|
|
proc setupELClient*(chainFile: string, enableAuth: bool): TestEnv =
|
2022-04-11 10:00:39 +00:00
|
|
|
result = TestEnv(
|
|
|
|
conf: makeConfig(@["--engine-signer:658bdf435d810c91414ec09147daa6db62406379", "--custom-network:" & genesisFile])
|
|
|
|
)
|
2022-07-18 04:34:42 +00:00
|
|
|
setupELClient(result, chainFile, enableAuth)
|
2022-04-11 10:00:39 +00:00
|
|
|
|
|
|
|
proc stopELClient*(t: TestEnv) =
|
|
|
|
waitFor t.rpcClient.close()
|
|
|
|
waitFor t.sealingEngine.stop()
|
2022-07-18 04:34:42 +00:00
|
|
|
#waitFor t.rpcServer.stop()
|
2022-04-11 10:00:39 +00:00
|
|
|
waitFor t.rpcServer.closeWait()
|
|
|
|
|
|
|
|
# TTD is the value specified in the TestSpec + Genesis.Difficulty
|
|
|
|
proc setRealTTD*(t: TestEnv, ttdValue: int64) =
|
|
|
|
let realTTD = t.gHeader.difficulty + ttdValue.u256
|
|
|
|
t.chainDB.config.terminalTotalDifficulty = some(realTTD)
|
|
|
|
t.ttd = realTTD
|
|
|
|
t.clmock = newCLMocker(t.rpcClient, realTTD)
|
|
|
|
|
2022-06-27 13:18:54 +00:00
|
|
|
proc slotsToSafe*(t: TestEnv, x: int) =
|
|
|
|
t.clMock.slotsToSafe = x
|
|
|
|
|
|
|
|
proc slotsToFinalized*(t: TestEnv, x: int) =
|
|
|
|
t.clMock.slotsToFinalized = x
|
|
|
|
|
2022-08-22 11:36:08 +00:00
|
|
|
func gwei(n: int64): GasInt {.compileTime.} =
|
2022-04-11 10:00:39 +00:00
|
|
|
GasInt(n * (10 ^ 9))
|
|
|
|
|
|
|
|
proc makeNextTransaction*(t: TestEnv, recipient: EthAddress, amount: UInt256, payload: openArray[byte] = []): Transaction =
|
|
|
|
const
|
|
|
|
gasLimit = 75000.GasInt
|
|
|
|
gasPrice = 30.gwei
|
|
|
|
|
|
|
|
let chainId = t.conf.networkParams.config.chainId
|
|
|
|
let tx = Transaction(
|
|
|
|
txType : TxLegacy,
|
|
|
|
chainId : chainId,
|
|
|
|
nonce : AccountNonce(t.nonce),
|
|
|
|
gasPrice: gasPrice,
|
|
|
|
gasLimit: gasLimit,
|
|
|
|
to : some(recipient),
|
|
|
|
value : amount,
|
|
|
|
payload : @payload
|
|
|
|
)
|
|
|
|
|
|
|
|
inc t.nonce
|
|
|
|
signTransaction(tx, t.vaultKey, chainId, eip155 = true)
|
2022-05-29 04:23:03 +00:00
|
|
|
|
|
|
|
proc verifyPoWProgress*(t: TestEnv, lastBlockHash: Hash256): bool =
|
|
|
|
let res = waitFor verifyPoWProgress(t.rpcClient, lastBlockHash)
|
|
|
|
if res.isErr:
|
|
|
|
error "verify PoW Progress error", msg=res.error
|
|
|
|
return false
|
2022-06-14 06:04:12 +00:00
|
|
|
|
2022-05-29 04:23:03 +00:00
|
|
|
true
|