¿Cuál es la forma más rápida de minar una transacción para poder probar contratos rápidamente?

Estoy desarrollando un marco de prueba automatizado de solidez en nodejs que usa eventos/registro de forma extensiva. El uso de eventos elimina (creo) todos los simuladores de RPC que existen. También es frustrante perseguir los problemas del simulador, prefiero usar un servidor real que esté modificado para ir más rápido.

He pirateado geth para extraer transacciones cada 4 segundos en lugar de 15-20 segundos, pero sigue siendo demasiado lento. Me gustaría ejecutar tan rápido como la VM pueda ejecutar el código.

Voy a publicar mi parche para geth para hacer esto, pero a mí y a otros realmente nos gustaría una mejor respuesta a esta pregunta. Realmente ralentiza el desarrollo tener que esperar varios segundos para que se complete cada transacción. Mi conjunto de pruebas de unas 60 transacciones tarda entre 4 y 5 minutos en ejecutarse, y mi conjunto de pruebas se hace cada vez más largo...

Aconseje sobre cómo hacer que este geth sea mío incluso más rápido que la respuesta que propongo, o también una sugerencia alternativa.

Respuestas (3)

Parche a geth para hacerlo mío más rápido. Realmente me gustaría recibir ayuda para hacer esto entre 2 y 4 veces más rápido de lo que es ahora, pero es 5 veces más rápido que el stock geth:

[9 de marzo de 2016 EDITAR: este nuevo parche ahora se extrae cada segundo. Mis pruebas unitarias que ejecutan 78 transacciones se ejecutan en aproximadamente 160 segundos. Debería publicar una Gist para esto...]

    diff --git a/eth/fetcher/fetcher.go b/eth/fetcher/fetcher.go
index d88d919..f03fd30 100644
--- a/eth/fetcher/fetcher.go
+++ b/eth/fetcher/fetcher.go
@@ -34,7 +34,7 @@ import (
 const (
    arriveTimeout = 500 * time.Millisecond // Time allowance before an announced block is explicitlrd
    gatherSlack   = 100 * time.Millisecond // Interval used to collate almost-expired announces witfs
-   fetchTimeout  = 5 * time.Second        // Maximum alloted time to return an explicitly requestebk
+   fetchTimeout  = 1 * time.Second        // Maximum alloted time to return an explicitly requestebk
    maxUncleDist  = 7                      // Maximum allowed backward distance from the chain head
    maxQueueDist  = 32                     // Maximum allowed distance from the chain head to queue
    hashLimit     = 256                    // Maximum number of unique blocks a peer may have annoued
diff --git a/eth/peer.go b/eth/peer.go
index 15ba22f..0201057 100644
--- a/eth/peer.go
+++ b/eth/peer.go
@@ -41,7 +41,7 @@ var (
 const (
    maxKnownTxs      = 32768 // Maximum transactions hashes to keep in the known list (prevent DOS)
    maxKnownBlocks   = 1024  // Maximum block hashes to keep in the known list (prevent DOS)
-   handshakeTimeout = 5 * time.Second
+   handshakeTimeout = 1 * time.Second
 )

 // PeerInfo represents a short summary of the Ethereum sub-protocol metadata known
diff --git a/miner/worker.go b/miner/worker.go
index 754a6fc..2b62b59 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -466,7 +466,7 @@ func (self *worker) commitNewWork() {
            tstamp = parent.Time().Int64() + 1
    }
    // this will ensure we're not going off too far in the future
-   if now := time.Now().Unix(); tstamp > now+4 {
+   if now := time.Now().Unix(); tstamp > now {
            wait := time.Duration(tstamp-now) * time.Second
            glog.V(logger.Info).Infoln("We are too far in the future. Waiting for", wait)
            time.Sleep(wait)
diff --git a/p2p/rlpx.go b/p2p/rlpx.go
index aaa7338..ce82eb7 100644
--- a/p2p/rlpx.go
+++ b/p2p/rlpx.go
@@ -57,7 +57,7 @@ const (

    // total timeout for encryption handshake and protocol
    // handshake in both directions.
-   handshakeTimeout = 5 * time.Second
+   handshakeTimeout = 2 * time.Second

    // This is the timeout for sending the disconnect reason.
    // This is shorter than the usual timeout because we don't want
diff --git a/params/protocol_params.go b/params/protocol_params.go
index dcc17e0..21a49c5 100755
--- a/params/protocol_params.go
+++ b/params/protocol_params.go
@@ -29,10 +29,10 @@ var (
    CallNewAccountGas      = big.NewInt(25000)  // Paid for CALL when the destination address didn'e.
    TxGas                  = big.NewInt(21000)  // Per transaction. NOTE: Not payable on data of cas.
    TxDataZeroGas          = big.NewInt(4)      // Per byte of data attached to a transaction that u.
-   DifficultyBoundDivisor = big.NewInt(2048)   // The bound divisor of the difficulty, used in thep.
+   DifficultyBoundDivisor = big.NewInt(1)      // The bound divisor of the difficulty, used in thep.
    QuadCoeffDiv           = big.NewInt(512)    // Divisor for the quadratic particle of the memoryo.
-   GenesisDifficulty      = big.NewInt(131072) // Difficulty of the Genesis block.
-   DurationLimit          = big.NewInt(13)     // The decision boundary on the blocktime duration e.
+   GenesisDifficulty      = big.NewInt(1)      // Difficulty of the Genesis block.
+   DurationLimit          = big.NewInt(1)      // The decision boundary on the blocktime duration e.
    SstoreSetGas           = big.NewInt(20000)  // Once per SLOAD operation.
    LogDataGas             = big.NewInt(8)      // Per byte in a LOG* operation's data.
    CallStipend            = big.NewInt(2300)   // Free gas given at beginning of call.
@@ -57,7 +57,7 @@ var (
    CreateDataGas        = big.NewInt(200)    //
    Ripemd160Gas         = big.NewInt(600)    //
    Ripemd160WordGas     = big.NewInt(120)    //
-   MinimumDifficulty    = big.NewInt(131072) // The minimum that the difficulty may ever be.
+   MinimumDifficulty    = big.NewInt(1)      // The minimum that the difficulty may ever be.
    CallCreateDepth      = big.NewInt(1024)   // Maximum depth of call/create stack.
    ExpGas               = big.NewInt(10)     // Once per EXP instuction.
    LogGas               = big.NewInt(375)    // Per LOG* operation.

Aquí está mi genesis.json. Hay muchos otros ejemplos por ahí:

{
    "nonce": "0xdeadbeefdeadbeef",
    "timestamp": "0x0",
    "parentHash":     "0x0000000000000000000000000000000000000000000000000000000000000000",
    "extraData": "0x0",
    "gasLimit": "0x8000000",
    "difficulty": "0x001",
    "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "coinbase": "0x3333333333333333333333333333333333333333",
    "alloc": {
        "0x662eb875377b1288f07baa6139432553b7b8b03e": {
            "balance": "1000000000000000000000"
         }
    }
}

~

Y finalmente la línea de comando más importante. Tenga en cuenta que he cambiado el costo de la gasolina a 50 wei en lugar de 50Gwei. Probablemente podría haberlo hecho mejor si simplemente le diera a un montón de cuentas 10 millones de éter. También necesito agregar la lectura de un script que desbloquea todas las cuentas:

#!/bin/bash
bin/geth --datadir /home/Pauls/testing/00 --port 30310 --rpc --rpcport 8110 --networkid 4567890 --dev --lightkdf --nodiscover --maxpeers 0 --vmdebug --verbosity 6 --pprof --genesis /home/Pauls/sandboxes/myproj/bin/genesis.json --gpomin "50" --gpomax "50" --pprofport 6110 console 2> /home/Pauls/testing/00/geth.log

~

Me han dicho que testrpc ahora admite eventos. Lo probaré cuando tenga algo de tiempo.

Test-RPC es una gran aplicación para hacer exactamente esto. Ejecuta una cadena de bloques simulada, a la que puede conectarse a través de RPC a través de web3, y no necesita minar ni conectarse en red en absoluto.

En un momento, testrpc no admitió eventos. Parece que ahora. Además, necesito un servidor, no una biblioteca, porque estoy haciendo una aplicación de múltiples partes. No obstante lo intentaré
En realidad, es un servidor. me expresé mal
Entonces, ¿cómo se compara eso con github.com/ethereumjs/testrpc?
Ese se ejecuta en un cliente NodeJS simplificado, el que publiqué se ejecuta en una bifurcación del cliente python. Sin embargo, parece que el JS admite eventos ahora, por lo que puede ser mejor.
Recientemente probé el testrpc de nodejs frente al parche geth anterior. Lo creas o no, las minas geth son más rápidas con el parche anterior. Algo sucedió desde la versión anterior de ethereumjs/testrpc para ralentizarlo.

Una alternativa es usar pyethereum.tester, pytester para abreviar (y no debe confundirse con py.test).

pytester es parte de pyethereum , el cliente python de la Fundación Ethereum que se ha sometido a una auditoría de seguridad (como Geth) y forma parte del Programa Ethereum Bounty . De acuerdo, es frustrante perseguir los problemas del simulador y no lo clasificaría como tal: ha sido muy confiable y un error encontrado al usar pytester bien podría ser un problema de consenso en el propio pyethereum y digno de una recompensa.

https://github.com/ethereum/pyethereum/wiki/Using-pyethereum.tester

Como preguntó específicamente sobre la minería, aquí hay un ejemplo de minería de 105 bloques s.mine(105):

from ethereum import tester as t
def test_make_reports():
    global initial_gas
    initial_gas = 0
    t.gas_limit = 100000000
    s = t.state()
    c = s.abi_contract('functions/output.se')
    gas_use(s)
    c.initiateOwner(1010101)
    c.reputationFaucet(1010101)
    assert(c.submitReportHash(1010101, 3232, -1, 222, 0)==-2), "Nonexistant event check broken"
    event1 = c.createEvent(1010101, "new event", 5, 1, 2, 2)
    bin_market = c.createMarket(1010101, "new market", 2**58, 100*2**64, 184467440737095516, [event1], 1)
    s.mine(105)
    gas_use(s)
    c.incrementPeriod(1010101)
    report_hash = c.makeHash(0, 2**64, event1)
    gas_use(s)
    print c.submitReportHash(1010101, report_hash, 0, event1, 0)
    assert(c.submitReportHash(1010101, report_hash, 0, event1, 0)==1), "Report hash submission failed"
    gas_use(s)
    s.mine(55)
    gas_use(s)
    assert(c.submitReport(1010101, 0, 0, 0, 2**64, event1, 2**64)==1), "Report submission failed"
    gas_use(s)
    print c.getUncaughtOutcome(event1)
    gas_use(s)
    print "Test make reports OK"

pytester también funciona con código Solidity. Ethereum Alarm Clock usa pytester para extraer muchos bloques para que pueda probar, por ejemplo, que el reloj se despierta en un futuro lejano. El wait_for_blockes a través de Populus , un marco que usa pytester; Populus también tiene la opción de probar usando un nodo Geth real.

Otro ejemplo de Solidity que sugiere el poder de pytester para probar escenarios arbitrariamente complejos, es con ether_ad, bajo el dapp-bin de Ethereum .

bueno, estoy usando nodejs, no python. ¿Puedo simplemente configurar pytest para escuchar en un socket como geth, pero el mío lo más rápido posible, sin tener que escribir ningún (o al menos muy poco) código de python?
No estoy seguro de si pytester se puede usar así: sería genial si pudiera y, por ahora, es mejor preguntar en gitter.im/ethereum/pyethereum (probablemente una respuesta más rápida de esa manera)