@@ -28,6 +28,7 @@ import (
2828 "github.com/ethereum/go-ethereum/common/hexutil"
2929 "github.com/ethereum/go-ethereum/common/math"
3030 "github.com/ethereum/go-ethereum/consensus/clique"
31+ "github.com/ethereum/go-ethereum/consensus/ethash"
3132 "github.com/ethereum/go-ethereum/core/types"
3233 "github.com/ethereum/go-ethereum/crypto"
3334 "github.com/ethereum/go-ethereum/log"
@@ -73,9 +74,11 @@ type bbInput struct {
7374 Withdrawals []* types.Withdrawal `json:"withdrawals,omitempty"`
7475 Clique * cliqueInput `json:"clique,omitempty"`
7576
76- Ethash bool `json:"-"`
77- Txs []* types.Transaction `json:"-"`
78- Ommers []* types.Header `json:"-"`
77+ Ethash bool `json:"-"`
78+ EthashDir string `json:"-"`
79+ PowMode ethash.Mode `json:"-"`
80+ Txs []* types.Transaction `json:"-"`
81+ Ommers []* types.Header `json:"-"`
7982}
8083
8184type cliqueInput struct {
@@ -159,13 +162,42 @@ func (i *bbInput) ToBlock() *types.Block {
159162// SealBlock seals the given block using the configured engine.
160163func (i * bbInput ) SealBlock (block * types.Block ) (* types.Block , error ) {
161164 switch {
165+ case i .Ethash :
166+ return i .sealEthash (block )
162167 case i .Clique != nil :
163168 return i .sealClique (block )
164169 default :
165170 return block , nil
166171 }
167172}
168173
174+ // sealEthash seals the given block using ethash.
175+ func (i * bbInput ) sealEthash (block * types.Block ) (* types.Block , error ) {
176+ if i .Header .Nonce != nil {
177+ return nil , NewError (ErrorConfig , fmt .Errorf ("sealing with ethash will overwrite provided nonce" ))
178+ }
179+ ethashConfig := ethash.Config {
180+ PowMode : i .PowMode ,
181+ DatasetDir : i .EthashDir ,
182+ CacheDir : i .EthashDir ,
183+ DatasetsInMem : 1 ,
184+ DatasetsOnDisk : 2 ,
185+ CachesInMem : 2 ,
186+ CachesOnDisk : 3 ,
187+ }
188+ engine := ethash .New (ethashConfig , nil , true )
189+ defer engine .Close ()
190+ // Use a buffered chan for results.
191+ // If the testmode is used, the sealer will return quickly, and complain
192+ // "Sealing result is not read by miner" if it cannot write the result.
193+ results := make (chan * types.Block , 1 )
194+ if err := engine .Seal (nil , block , results , nil ); err != nil {
195+ panic (fmt .Sprintf ("failed to seal block: %v" , err ))
196+ }
197+ found := <- results
198+ return block .WithSeal (found .Header ()), nil
199+ }
200+
169201// sealClique seals the given block using clique.
170202func (i * bbInput ) sealClique (block * types.Block ) (* types.Block , error ) {
171203 // If any clique value overwrites an explicit header value, fail
@@ -235,8 +267,28 @@ func readInput(ctx *cli.Context) (*bbInput, error) {
235267 withdrawalsStr = ctx .String (InputWithdrawalsFlag .Name )
236268 txsStr = ctx .String (InputTxsRlpFlag .Name )
237269 cliqueStr = ctx .String (SealCliqueFlag .Name )
270+ ethashOn = ctx .Bool (SealEthashFlag .Name )
271+ ethashDir = ctx .String (SealEthashDirFlag .Name )
272+ ethashMode = ctx .String (SealEthashModeFlag .Name )
238273 inputData = & bbInput {}
239274 )
275+ if ethashOn && cliqueStr != "" {
276+ return nil , NewError (ErrorConfig , fmt .Errorf ("both ethash and clique sealing specified, only one may be chosen" ))
277+ }
278+ if ethashOn {
279+ inputData .Ethash = ethashOn
280+ inputData .EthashDir = ethashDir
281+ switch ethashMode {
282+ case "normal" :
283+ inputData .PowMode = ethash .ModeNormal
284+ case "test" :
285+ inputData .PowMode = ethash .ModeTest
286+ case "fake" :
287+ inputData .PowMode = ethash .ModeFake
288+ default :
289+ return nil , NewError (ErrorConfig , fmt .Errorf ("unknown pow mode: %s, supported modes: test, fake, normal" , ethashMode ))
290+ }
291+ }
240292 if headerStr == stdinSelector || ommersStr == stdinSelector || txsStr == stdinSelector || cliqueStr == stdinSelector {
241293 decoder := json .NewDecoder (os .Stdin )
242294 if err := decoder .Decode (inputData ); err != nil {
0 commit comments