Are transactions with ring signatures available in Ethereum? There should be as anonymity/fungibility is important.

Also, I think Vitalk Buterin mentioned it may be possible to implement an EVM operation that allows for less gas usage for ring transactions. Did I get that right? If so, what is the operation and is anyone working on implementing it in the EVM?

up vote 8 down vote accepted

In a January 15 2016 blog post, Vitalik mentions:

Ring signatures are more mathematically involved than simple signatures, but they are quite practical to implement; some sample code for ring signatures on top of Ethereum can be found here.

Here is a snippet:

def verify(msgHash:bytes32, x0:uint256, s:uint256[], Ix:uint256, Iy:uint256, pub_xs:uint256[], pub_ys:bytes):
    # Number of pubkeys
    n = len(pub_xs)
    # Decompress the provided I value
    Iy = recover_y(Ix, Iy)
    # Store the list of intermediate values in the "ring"
    e = array(n + 1)
    # Set the first value in the ring to that provided in the signature
    e[0] = [x0, sha3(x0)]
    i = 1
    while i < n + 1:
        prev_i = (i - 1) % n
        # Decompress the public key
        pub_yi = recover_y(pub_xs[i % n], bit(pub_ys, i % n))
        # Create the next values in the ring based on the provided s value
        k1 = ecmul(Gx, Gy, 1, s[prev_i])
        k2 = ecmul(pub_xs[i % n], pub_yi, 1, e[prev_i][1])
        pub1 = decompose(ecsubtract(k1, k2))
        k3 = self.hash_pubkey_to_pubkey([pub_xs[i % n], pub_yi], outitems=2)
        k4 = ecmul(k3[0], k3[1], 1, s[prev_i])
        k5 = ecmul(Ix, Iy, 1, e[prev_i][1])
        pub2 = decompose(ecsubtract(k4, k5))
        left = sha3([msgHash, pub1[0], pub1[1], pub2[0], pub2[1]]:arr)
        right = sha3(left)
        # FOR DEBUGGING
        # if i >= 1:
        #     log(type=PubkeyLogEvent, pub_xs[i], pub_yi)
        #     log(type=PubkeyLogEvent, pub1[0], pub1[1])
        #     log(type=PubkeyLogEvent, pub2[0], pub2[1])
        #     log(type=ValueLogEvent, left)
        #     log(type=ValueLogEvent, right)
        e[i] = [left, right]
        i += 1
    # Check that the ring is consistent
    return((e[n][0] == e[0][0] and e[n][1] == e[0][1]):bool)

Note, the top of the file does say "TOTALLY NOT TESTED AND LIKELY BROKEN AT THIS POINT; AWAITING A TEST SUITE".

EDIT by user @bleepbloop: Vitalik has confirmed that this is a very early PoC and not fully functional at present.

Looking at the code again, I think I = Ix, Iy is the 'tag' that makes this scheme linkable, there just isn't yet a function to store and compare the I values that have been previously seen, which would be needed in order to prevent double spending/double withdrawals.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.