private bool SubmitBlock(IShare share) { // TODO: we should try different submission techniques and probably more then once: https://github.com/ahmedbodi/stratum-mining/blob/master/lib/bitcoin_rpc.py#L65-123 try { _daemonClient.SubmitBlock(share.BlockHex.ToHexString()); var block = _blockProcessor.GetBlock(share.BlockHash.ToHexString()); // query the block. if (block == null) // make sure the block exists { return(false); } if (block.Confirmations == -1) // make sure the block is accepted. { _logger.Debug("Submitted block {0:l} is orphaned", block.Hash); return(false); } var expectedTxHash = share.CoinbaseHash.Bytes.ReverseBuffer().ToHexString(); // calculate our expected generation transactions's hash var genTxHash = block.Tx.First(); // read the hash of very first (generation transaction) of the block if (expectedTxHash != genTxHash) // make sure our calculated generated transaction and one reported by coin daemon matches. { _logger.Debug("Submitted block {0:l} doesn't seem to belong us as reported generation transaction hash [{1:l}] doesn't match our expected one [{2:l}]", block.Hash, genTxHash, expectedTxHash); return(false); } var genTx = _blockProcessor.GetGenerationTransaction(block); // get the generation transaction. var poolOutput = _blockProcessor.GetPoolOutput(genTx); // get the output that targets pool's central address. // make sure the blocks generation transaction contains our central pool wallet address if (poolOutput == null) { _logger.Debug("Submitted block doesn't seem to belong us as generation transaction doesn't contain an output for pool's central wallet address: {0:}", _poolConfig.Wallet.Adress); return(false); } // if the code flows here, then it means the block was succesfully submitted and belongs to us. share.SetFoundBlock(block, genTx); // assign the block to share. return(true); } catch (Exception e) { _logger.Error("Submit block failed - height: {0}, hash: {1:l} - {2:l}", share.Height, share.BlockHash.ToHexString(), e.Message); return(false); } }
private void DetectSubmitBlockSupport() { // issue a submitblock() call too see if it's supported. // If the coin supports the submitblock() call it's should return a RPC_DESERIALIZATION_ERROR (-22) - 'Block decode failed' as we just supplied an empty string as block hash. // otherwise if it doesn't support the call, it should return a RPC_METHOD_NOT_FOUND (-32601) - 'Method not found' error. try { var response = _daemonClient.SubmitBlock(string.Empty); } catch (RpcException e) { if (e is RpcErrorException) { var error = e as RpcErrorException; switch (error.Code) { case (int)RpcErrorCode.RPC_METHOD_NOT_FOUND: _poolConfig.Coin.Options.SubmitBlockSupported = false; // the coin doesn't support submitblock(). _logger.Debug("submitblock() is NOT SUPPORTED by your wallet"); break; case (int)RpcErrorCode.RPC_DESERIALIZATION_ERROR: _poolConfig.Coin.Options.SubmitBlockSupported = true; // the coin supports submitblock(). _logger.Debug("submitblock() is SUPPORTED by your wallet"); break; default: _logger.Error("Recieved an unexpected response for DetectSubmitBlockSupport() - {0}, {1:l}", error.Code, e.Message); break; } } else { _logger.Error("Can not probe submitblock() support: {0:l}", e.Message); } } }
private bool SubmitBlock(IShare share) { // TODO: we should try different submission techniques and probably more then once: https://github.com/ahmedbodi/stratum-mining/blob/master/lib/bitcoin_rpc.py#L65-123 try { if (_poolConfig.Coin.Options.SubmitBlockSupported) // see if submitblock() is available. { _daemonClient.SubmitBlock(share.BlockHex.ToHexString()); // submit the block. } else { _daemonClient.GetBlockTemplate(share.BlockHex.ToHexString(), _poolConfig.Wallet.Address); // use getblocktemplate() if submitblock() is not supported. } var block = _daemonClient.GetBlock(share.BlockHash.ToHexString()); // query the block. if (block == null) // make sure the block exists { _logger.Debug("Submitted block [{0}] cannot be found with getblock; [{1}]", share.BlockHash.ToHexString(), block.Hash); return(false); } if (block.Confirmations == -1) // make sure the block is accepted. { _logger.Debug("Submitted block [{0}] is orphaned; [{1:l}]", block.Height, block.Hash); return(false); } var expectedTxHash = share.CoinbaseHash.Bytes.ReverseBuffer().ToHexString(); // calculate our expected generation transactions's hash var genTxHash = block.Tx.First(); // read the hash of very first (generation transaction) of the block if (expectedTxHash != genTxHash) // make sure our calculated generated transaction and one reported by coin daemon matches. { _logger.Debug("Submitted block [{0}] doesn't seem to belong us as reported generation transaction hash [{1:l}] doesn't match our expected one [{2:l}]", block.Height, genTxHash, expectedTxHash); return(false); } var genTx = _daemonClient.GetTransaction(block.Tx.First()); // get the generation transaction. // make sure we were able to read the generation transaction if (genTx == null) { _logger.Debug("Submitted block [{0}] doesn't seem to belong us as we can't read the generation transaction on our records [{1:l}]", block.Height, block.Tx.First()); return(false); } var poolOutput = genTx.GetPoolOutput(_poolConfig.Wallet.Address, _poolAccount); // get the output that targets pool's central address. // make sure the blocks generation transaction contains our central pool wallet address if (poolOutput == null) { _logger.Debug("Submitted block [{0}] doesn't seem to belong us as generation transaction doesn't contain an output for pool's central wallet address: {0:}", block.Height, _poolConfig.Wallet.Address); return(false); } // if the code flows here, then it means the block was succesfully submitted and belongs to us. share.SetFoundBlock(block, genTx); // assign the block to share. _logger.Information("Found block [{0}] with hash [{1:l}]", share.Height, share.BlockHash.ToHexString()); return(true); } catch (RpcException e) { // unlike BlockProcessor's detailed exception handling and decision making based on the error, // here in share-manager we only one-shot submissions. If we get an error, basically we just don't care about the rest // and flag the submission as failed. _logger.Debug("We thought a block was found but it was rejected by the coin daemon; [{0:l}] - reason; {1:l}", share.BlockHash.ToHexString(), e.Message); return(false); } catch (Exception e) { _logger.Debug("We thought a block was found but it was rejected by the coin daemon; [{0:l}] - reason; {1:l}", share.BlockHash.ToHexString(), e.Message); return(false); } }