pipermerriam/ethereum-function-signature-registry

Make registry into on-chain contract

Opened this issue · 6 comments

It would be really cool if this registry lived on-chain!

I mentioned this to you, and you said there were some caveats we needed to overcome first, and you'd be happy to discuss it in an issue here, so here we go!

cc @kumavis

The current hurdle (from my perspective) is as follows.

The basics of the contract would be as follows.

note this should be considered psuedo code and not well thought out contract code.

contract FunctionSignatureRegistry {
    mapping (bytes4 => string[]) _lookup;
    mapping (bytes32 => bool) _registeredSignatures;

    function isCanonical(string textSignature) constant returns (bool) {
        // Need to validate that the string is in the canonical form.
        // good: transfer(address,uint256)
        // bad: transfer(address,uint)
        ...
    }

    function register(string textSignature) returns (bool) {
        // Check if the text version of the signature has already been registered
        if (!_registeredSignatures[sha3(textSignature)]) {
            // Check that the signature is in the canonical form
            if (!isCanonical(textSignature)) throw;

            // Push the text signature onto the mapping
            _lookup[bytes4(sha3(textSignature))].push(textSignature);

            // make not that we have now seen this textSignature
            _registeredSignatures[sha3(textSignature)];

            return true;
        } else {
            return false;
        }
    }

    function query(bytes4 bytesSignature) returns (string[]) {
        // return the array of text signatures that map to this 4-byte value.
        return _lookup[bytesSignature];
    }
}

The missing part is the validation portion. We only want to register 4-byte signatures for valid canonical signatures. Otherwise it's trivial to populate the database with other strings that are not valid canonical function signatures and that collide with valid 4-byte signatures.

This would mean that when someone queried the database they would need to do this validation on their own, which in my opinion isn't an acceptable property of this database. Once we can do this validation then I plan to migrate the registry into an on-chain contract backed format.

we could always just validate the hash and have the front-end validate the abi... since storing junk in there comes at cost to the attacker

Otherwise it's trivial to populate the database with other strings that are not valid canonical function signatures and that collide with valid 4-byte signatures.

right it would need to be mapping method_Id->method_signature[], not sure if solidity supports that

This would mean that when someone queried the database they would need to do this validation on their own, which in my opinion isn't an acceptable property of this database.

yeah, but maybe better than further belaboring the submitters?

worth noting that the validation code may need to alter as solidity evolves

The nice thing is if solidity evolved to need new validations, you could just make a new contract that falls back to the older one for its data storage/retrieval.

I agree the easy way out is skipping the form validation, and ideally consumers of the registry do a validation on the results (which could hopefully be an array), to find valid results that have the correct form.

Any UIs created could also perform validation beforehand as a bonus convenience.

If I think about possible types of attacks, it might involve generating a method signature that matches a trusted method signature, or submitting a trustworthy-looking ABI for a contract with malicious parameters.

In the first case, the attack wouldn't be thwarted by any type of validation. In the second case, there's nothing really keeping a user from just using trustworthy looking parameters.

So as far as I can tell, the validations are mostly for keeping the data clean, not necessarily more secure, so I think validations on the UIs that use such a registry would be adequate.

worth noting that the validation code may need to alter as solidity evolves

I was under the impression that this was a general ethereum specification thing. https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI#function-selector

but maybe better than further belaboring the submitters?

I'm not really sure I understand how this belabors submitters.

we could always just validate the hash and have the front-end validate the abi... since storing junk in there comes at cost to the attacker

This approach falls into the category of "unsafe defaults". If the registry returns function signatures that are invalid function signatures then it feels like just kicking the can down the road to the API consumer. I would much rather wait and deploy an API that only returns function signatures that are valid.

All of that said......

I am of course not going to stand in the way of anyone else deploying this service as a contract. In fact, if you'd like to do so I'll happily provide you with a full export (or a script to pull a full export) of the current database. I personally am not likely to undertake this until I can write something that does the appropriate validation.

One possible middle ground would be to deploy something that wasn't trustless and just had a set of privileged submitters.

yeah ideally you would provide a js module that takes a provider and does the lookups for you and that can ship with the validation code