Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Miner info is empty in block #17454

Closed
APshenkin opened this issue Aug 20, 2018 · 7 comments
Closed

Miner info is empty in block #17454

APshenkin opened this issue Aug 20, 2018 · 7 comments

Comments

@APshenkin
Copy link

Hi!

Trying to get information about blocks. For this I use web3 methods. All information displays normaly expect miner address. Tested in rinkeby network

System information

Geth version: 1.8.13
OS & Version: Linux

Expected behaviour

Miner address should be present in block information

Actual behaviour

Miner address in null 0x0000000000000000000000000000000000000000

Steps to reproduce the behaviour

  1. Run geth geth --rpc --rpcaddr 0.0.0.0 --rpcvhosts * --rinkeby --syncmode "fast"
  2. Try to get information about any block, e.g.
eth.getBlock(2848394)

{
  difficulty: 1,
  extraData: "0xd68301080d846765746886676f312e3130856c696e7578000000000000000000773ab2ca8f47904a14739ad80a75b71d9d29b9fff8b7ecdcb73efffa6f74122f17d304b5dc8e6e5f256c9474dd115c8d4dae31b7a3d409e5c3270f8fde41cd8c00",
  gasLimit: 7753377,
  gasUsed: 1810195,
  hash: "0x7004c895e812c55b0c2be8a46d72ca300a683dc27d1d7917ee7742d4d0359c1f",
  logsBloom: "0x00000000000000020000000000002000000400000000000000000000000000000000000000000000040000080004000020000010000000000000000000000000000000000000000008000008000000000000000000200000000000000000000000000000020000000000000000000800000000000000804000000010080000000800000000000000000000000000000000000000000000800000000000080000000008000400000000404000000000000000000000000200000000000000000000000002000000000000001002000000000000002000000008000000000020000000000000000000000000000000000000000000000000400000800000000000",
  miner: "0x0000000000000000000000000000000000000000",
  mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  nonce: "0x0000000000000000",
  number: 2848394,
  parentHash: "0x20350fc367e19d3865be1ea7da72ab81f8f9941c43ac6bb24a34a0a7caa2f3df",
  receiptsRoot: "0x6ade4ac1079ea50cfadcce2b75ffbe4f9b14bf69b4607bbf1739463076ca6246",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 6437,
  stateRoot: "0x23f63347851bcd109059d007d71e19c4f5e73b7f0862bebcd04458333a004d92",
  timestamp: 1534796040,
  totalDifficulty: 5353647,
  transactions: ["0x7e3bb851fc74a436826d2af6b96e4db9484431811ef0d9c9e78370488d33d4e5", "0x3976fd1e3d2a715c3cfcfde9bd3210798c26c017b8edb841d319227ecb3322fb", "0xd8db124005bb8b6fda7b71fd56ac782552a66af58fe843ba3c4930423b87d1d2", "0x10c1a1ca4d9f4b2bd5b89f7bbcbbc2d69e166fe23662b8db4f6beae0f50ac9fd", "0xaa58a6545677c796a56b8bc874174c8cfd31a6c6e6ca3a87e086d4f66d52858a"],
  transactionsRoot: "0xde8d25c0b9b54310128a21601331094b43f910f9f96102869c2e2dca94884bf4",
  uncles: []
}

Also found that in "light" mode the same issue appears. Also in "light" mode getTransaction return null instead transaction info.

So, is Miner address is availible only in "full" sync mode?

Kind regards

@rjl493456442
Copy link
Member

rjl493456442 commented Aug 21, 2018

@APshenkin The miner field in clique algorithm has a different meaning.

Basically, the miner (coinbase) field is used to indicate a target address for new signer proposal or delete signer proposal.

The signer signature has been included in the extraData field so that signer address can be recovered.

For more detail, please take a look at this proposal

@APshenkin
Copy link
Author

@rjl493456442 Thank you for clarifation. But still no luck to get info about signer address. I can't find any example how to do this.Is there a code snippet, how to get info about address from extraData?

@rjl493456442
Copy link
Member

Here is a code snippet copied from the clique consensus package. I think it should be similar for you to recover the signer address.

// ecrecover extracts the Ethereum account address from a signed header.
func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) {
	// If the signature's already cached, return that
	hash := header.Hash()
	if address, known := sigcache.Get(hash); known {
		return address.(common.Address), nil
	}
	// Retrieve the signature from the header extra-data
	if len(header.Extra) < extraSeal {
		return common.Address{}, errMissingSignature
	}
	signature := header.Extra[len(header.Extra)-extraSeal:]

	// Recover the public key and the Ethereum address
	pubkey, err := crypto.Ecrecover(sigHash(header).Bytes(), signature)
	if err != nil {
		return common.Address{}, err
	}
	var signer common.Address
	copy(signer[:], crypto.Keccak256(pubkey[1:])[12:])

	sigcache.Add(hash, signer)
	return signer, nil
}

@APshenkin
Copy link
Author

APshenkin commented Aug 21, 2018

@rjl493456442 Thanks a lot.

Trying to reformat it in JS, but no luck

const Web3 = require('web3')

const utils = require('ethereumjs-util')
const BlockHeader = require('ethereumjs-block/header')

const web3 = new Web3(new Web3.providers.HttpProvider('.....'))


const block = web3.eth.getBlock(2848394)

const hashBuff = Buffer.from(block.hash.replace('0x', ''), 'hex')
const dataBuff = Buffer.from(block.extraData.replace('0x', ''), 'hex')

const sig = dataBuff.slice(dataBuff.length - 65)
const signature = {
  r: sig.slice(0, 32),
  s: sig.slice(32, 64),
  v: 27
}

const pub = utils.ecrecover(hashBuff, signature.v, signature.r, signature.s)

const address = utils.pubToAddress(pub).toString('hex')

const checksumAddress = utils.toChecksumAddress(address);

const finalizeAddress = utils.addHexPrefix(checksumAddress);

But address don't match with address on rinkeby.etherscan.io

expected 0xfc18cbc391de84dbd87db83b20935d3e89f5dd91, actual 0x4b3fFff4829cD0c7bE57DE4CFdc7311d27d05166

So several questions more:

  1. Can I use Block hash from eth_getBlock, or I should compute it like here https://github.com/ethereum/go-ethereum/blob/master/consensus/clique/clique.go#L145
  2. I tried to create a block header hash like this:
const BlockHeader = require('ethereumjs-block/header')

const blockHeader = new BlockHeader({
  parentHash: Buffer.from(block.parentHash.replace('0x', ''), 'hex'),
  uncleHash: Buffer.from(block.sha3Uncles.replace('0x', ''), 'hex'),
  coinbase: Buffer.from(block.miner.replace('0x', ''), 'hex'),
  stateRoot: Buffer.from(block.stateRoot.replace('0x', ''), 'hex'),
  transactionTrie: Buffer.from(block.transactionsRoot.replace('0x', ''), 'hex'),
  receiptTrie: Buffer.from(block.receiptsRoot.replace('0x', ''), 'hex'),
  bloom: Buffer.from(block.logsBloom.replace('0x', ''), 'hex'),
  difficulty: Buffer.from(block.difficulty.toString(16)),
  number: Buffer.from(block.number.toString()),
  gasLimit: Buffer.from(block.gasLimit.toString()),
  gasUsed: Buffer.from(block.gasUsed.toString()),
  timestamp: Buffer.from(block.timestamp.toString()),
  extraData: Buffer.from(block.extraData.replace('0x', ''), 'hex'),
  mixHash: Buffer.from(block.mixHash.replace('0x', ''), 'hex'),
  nonce: Buffer.from(block.nonce.replace('0x', ''), 'hex')
})

const hash = blockHeader.hash()

But this hash doesn't match etherscan hash and still no luck with address recover
expected 0xfc18cbc391de84dbd87db83b20935d3e89f5dd91, actual 0xdA06559899639406677230722047F298C74Db8c2. Maybe I do something wrong?

@APshenkin
Copy link
Author

APshenkin commented Aug 21, 2018

Other try

const Web3 = require('web3')

const utils = require('ethereumjs-util')
const BlockHeader = require('ethereumjs-block/header')
const web3 = new Web3(new Web3.providers.HttpProvider('......'))


const block = web3.eth.getBlock(2848394)

const hashBuff = Buffer.from(block.hash.replace('0x', ''), 'hex')
const dataBuff = Buffer.from(block.extraData.replace('0x', ''), 'hex')

const sig = dataBuff.slice(dataBuff.length - 65)
const signature = {
  r: sig.slice(0, 32),
  s: sig.slice(32, 64),
  v: 27
}

const sigHash = new BlockHeader({
  parentHash: Buffer.from(block.parentHash.replace('0x', ''), 'hex'),
  uncleHash: Buffer.from(block.sha3Uncles.replace('0x', ''), 'hex'),
  coinbase: Buffer.from(block.miner.replace('0x', ''), 'hex'),
  stateRoot: Buffer.from(block.stateRoot.replace('0x', ''), 'hex'),
  transactionTrie: Buffer.from(block.transactionsRoot.replace('0x', ''), 'hex'),
  receiptTrie: Buffer.from(block.receiptsRoot.replace('0x', ''), 'hex'),
  bloom: Buffer.from(block.logsBloom.replace('0x', ''), 'hex'),
  difficulty: utils.toBuffer(block.difficulty.toNumber()),
  number: utils.toBuffer(block.number),
  gasLimit: utils.toBuffer(block.gasLimit),
  gasUsed: utils.toBuffer(block.gasUsed),
  timestamp: utils.toBuffer(block.timestamp),
  extraData: Buffer.from(block.extraData.replace('0x', ''), 'hex').slice(0, dataBuff.length - 65),
  mixHash: Buffer.from(block.mixHash.replace('0x', ''), 'hex'),
  nonce: Buffer.from(block.nonce.replace('0x', ''), 'hex')
}, [4])

const pub = utils.ecrecover(sigHash.hash(), signature.v, signature.r, signature.s)

const address = utils.pubToAddress(pub).toString('hex')

still no luck address is now 0x57aa03773cd7550e216b4f3f3c9dc928cd881558

@rjl493456442
Copy link
Member

Yes, we should use special rlphash function(the second one is correct). You code seems good to me, have no idea for the incorrect result.

Btw, should utils.ecrecover returns an error if recover is failed?

@APshenkin
Copy link
Author

@rjl493456442
Finally found the mistake.
transactionTrie: Buffer.from(block.transactionsRoot.replace('0x', ''), 'hex'),
should be transactionsTrie: Buffer.from(block.transactionsRoot.replace('0x', ''), 'hex'),

So final implemenation with some code cleaning:

const Web3 = require('web3')

const utils = require('ethereumjs-util')
const BlockHeader = require('ethereumjs-block/header')

const web3 = new Web3(new Web3.providers.HttpProvider('...my node'))


const block = web3.eth.getBlock(2848394, true)

const dataBuff = utils.toBuffer(block.extraData)
const sig = utils.fromRpcSig(dataBuff.slice(dataBuff.length - 65, dataBuff.length))

block.extraData = '0x' + utils.toBuffer(block.extraData).slice(0, dataBuff.length - 65).toString('hex')

const headerHash = new BlockHeader({
  parentHash: utils.toBuffer(block.parentHash),
  uncleHash: utils.toBuffer(block.sha3Uncles),
  coinbase: utils.toBuffer(block.miner),
  stateRoot: utils.toBuffer(block.stateRoot),
  transactionsTrie: utils.toBuffer(block.transactionsRoot),
  receiptTrie: utils.toBuffer(block.receiptsRoot),
  bloom: utils.toBuffer(block.logsBloom),
  difficulty: utils.toBuffer(block.difficulty.toNumber()),
  number: utils.toBuffer(block.number),
  gasLimit: utils.toBuffer(block.gasLimit),
  gasUsed: utils.toBuffer(block.gasUsed),
  timestamp: utils.toBuffer(block.timestamp),
  extraData: utils.toBuffer(block.extraData),
  mixHash: utils.toBuffer(block.mixHash),
  nonce: utils.toBuffer(block.nonce)
})

const pub = utils.ecrecover(headerHash.hash(), sig.v, sig.r, sig.s)

const address = utils.addHexPrefix(utils.pubToAddress(pub).toString('hex'))

console.log(headerHash.hash().toString('hex'))
console.log(address) // returns expected result

Thanks a lot for help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants