ETCDEVTeam / sidekick-tx2poa

Maybe a proof of concept for an external javascript-based PoA mechanism
0 stars 1 forks source link

why not just take sha3 of authority signature, and fit it into single extraData field ? #2

Open whilei opened 6 years ago

whilei commented 6 years ago

@r8d8 said it first

whilei commented 6 years ago

Because you can't go "backward" from sha3.

Any node needs to be able to verify that the given sha3 (erm, keccak) is actually legit, and without also knowing the signature value it can't confirm that the sha3 is a legitimate hash, and thus can't confirm that the signature is valid.

r8d8 commented 6 years ago

Maybe to use full signature inside tx made from authority, and then sha3 inside block header?

whilei commented 6 years ago

I think that would work as well. I think it'd be pretty elegant. The only issue it leaves for me unresolved is a way to quickly identify the author's transaction.

If the block header contains only a sha3 of the signature, then to validate a block will require to query geth for each transaction to find the one with the block.miner === tx.from:

var authorsTransaction;
for (var i = 0; i < block.transactions.length; i++) {
    var _tx = eth.getTransactionByHash(block.transactions[i]);
    if (_tx.from !== block.miner) { continue; }
    authorsTransaction = eth.getBlock(_tx.hash);    
}

But by using a concatenation of the author's tx hash and signature in the block header, it allows the for loop to skip what might be a lot of eth.getTransactionByHash calls:

var authorsTransaction;
for (var i = 0; i < block.transactions.length; i++) {
    // can skip querying whole tx object for nonrelevant txs
    if (block.transactions[i].substring(0,8) !== block.extraData.substring(0,8)) { continue; }

    var _tx = eth.getTransactionByHash(block.transactions[i]);
    if (_tx.from !== block.miner) { continue; }
    authorsTransaction = eth.getBlock(_tx.hash);
    break;
}

So if we assume using a hybrid concatenated txhash.substring+rawOrShaSig.substring for the block.extraData field, then I guess using the sha3 only adds an extra layer of complexity.

whilei commented 6 years ago

And if we were to just use the transaction hash in the extraData field, it would be easy to forge:

// attacking miner
var pendingTxs = txpool.status.pending;
for (var i = 0; i < pendingTxs.length; i++) {
    if (authorities.indexOf(eth.getTransactionByHash(pendingTxs[i]).from) >= 0) {
        miner.setExtra(pendingTxs[i]);
    }
}

Or even more randomly and easily...

// attacking miner
// won't always successfully forge, but possible
if (txpool.status.pending.length > 0) { miner.setExtra(txpool.status.pending[0]); }
r8d8 commented 6 years ago

But how we can find first part of signature submitted in transaction by knowing second part of signature from extraData? It will also require linear search among all transactions inside block

whilei commented 6 years ago

We don't use the second part of signature to find first part -- we just know where to expect the second part of the signature and where to find the first part of the transaction hash:

https://github.com/ETCDEVTeam/sidekick-tx2poa/blob/master/tx2poa.js#L46

https://github.com/ETCDEVTeam/sidekick-tx2poa/blob/master/tx2poa.js#L225 https://github.com/ETCDEVTeam/sidekick-tx2poa/blob/master/tx2poa.js#L254

It does require a linear search through the transactions array, but doesn't require querying each transaction hash to check any transaction field, so difference in speed is just:

// faster
var knownPrefix = "0xabcdef"
for (hash in block.transactions) {
    if (hash.prefix === knownPrefix) {
        // this is the hash we want, a single query
        var tx = eth.getTransaction(hash)
        // do validation
    }
}

// vs. slower (more queries)
var wantHash = "0xabcdef..."
for (hash in block.transactions) {
    // have to query for each tx
    var tx = eth.getTransaction(hash)
    if (tx.data === wantHash) {
        // this is the hash we want
        // do validation
    }
}
r8d8 commented 6 years ago

But we still need to query transaction to get it's data field, or not? And how we get known prefix? I mean if there is bunch of authorities, then we will have multiple knownPrefix ?

whilei commented 6 years ago

We do need to query the transaction to get it's data field to derive a complete signature, but we know ahead of time which transaction to query (well, we know probably which transaction -- by prefix -- so ~1/((26+10)^6) probability of not getting a tx-hash-prefix collision -- and we still need to loop through the block.transactions until we find the right tx hash to query).

The known prefix is because the miner uses a standard pattern for his block's extraData field, where

var proofyTx.hash = "0xabcdef123123123123123123123123123123123";
var signature = "0xdeadbeefdeadbeefdeadbeefdeadbeef....";
block.extraData = "0xabcdef" + "deadbe" // proofyTx.hash.substring(0,8)+signature.substring(2,8)

https://github.com/ETCDEVTeam/sidekick-tx2poa/blob/master/tx2poa.js#L254

So for the validator to derive the relevant proof-tx, he does

var txPrefix = block.extraData.substring(0,8)
var sigPrefix = block.extraData.substring(8)
for (var i = 0; i < block.transactions.length; i++) {
    if (txPrefix === block.transactions[i].substring(0,8)) {
        var sigSuffix = parseSigSuffixFromTxData(eth.getTransaction(block.transactions[i]));    
        var minerSignature = personal.ecRecover(block.hash, sigPrefix+sigSuffix);
        var isValid = minerSignature === block.miner;
    }   
}

https://github.com/ETCDEVTeam/sidekick-tx2poa/blob/master/tx2poa.js#L123

Does that answer your question?

whilei commented 6 years ago

I mean if there is bunch of authorities, then we will have multiple knownPrefix ?

Since each authority submits an "incomplete proof of authority" transaction, there can be at least n authority transactions to "look through" to decide which one has the relevant signature for the block miner. And that's where the block header comes in; the authority makes his block header contain a clue that makes it so it's pretty easy to determine which transaction he wants you to use to validate his block.