There is still a problem with creation valid ECDSA points. I'm asking people who are more familiar with ECDSA if they know how we can calculate what a valid key must look like because right now the only option I see is brute-forcing the sequence number to a value that works. If anybody knows more about how to calculate a valid key please let me know.
Let's use the example earlier in this thread.
1.9.3-p286 :040 > (0..9).to_a.collect{|sequence| {sequence => Mastercoin::Util.valid_ecdsa_point?("020#{sequence}00000014000000020000000005f5e10000000000000f424006000000000001")} }
=> [{0=>true}, {1=>false}, {2=>false}, {3=>true}, {4=>true}, {5=>true}, {6=>false}, {7=>true}, {8=>false}, {9=>false}]
1.9.3-p286 :041 > (0..9).to_a.collect{|sequence| {sequence => Mastercoin::Util.valid_ecdsa_point?("020#{sequence}86a00000000000000000000000000000000000000000000000000000000000")} }
=> [{0=>true}, {1=>true}, {2=>false}, {3=>true}, {4=>true}, {5=>false}, {6=>true}, {7=>true}, {8=>true}, {9=>false}]
The result you see is the sequence number and whether this creates a valid point or not. As you can see it is very random and I don't know exactly why that is.
The other option is of course go Grazcoin's way and simply use invalid ECDSA points. Although I have no clue whether all Bitcoin implementations support this. And even if none of the implementations check the points, is this a well over thought decision or negligence.
Hey Tachikoma,
I'm still not learned enough on ECDSA (or elliptic curve cryptography in general) to really be too much help, let's hope someone with better knowledge of ECDSA can steer you in the right direction.
I don't think we should use invalid ECDSA points if at all possible though as we'd be making it blindingly easy to censor mastercoin; the bitcoin devs could simply enforce ECDSA point validity checking on multisig pubkeys and we'd be in trouble. We're doing what we can to minimize blockchain bloat by using provably redeemable outputs, but I'm conscious that they'll do what they think is in the best interests of bitcoin (rightly so) - it would likely come down to weighing up whatever reasons they may have for wanting to censor mastercoin against how expensive it would be (compute wise) having to verify ECDSA point validity on all output pubkeys.
If you don't get much help on understanding exactly why the keys are not valid ECDSA points there is an ugly solution; sequence numbers don't necessarily have to increment by one for each packet. As we include all packets in the same multisig output, when we create each packet we could check its ECDSA point validity (does y
2=x
3+(a*x)+b) and if it's not valid, move the sequence number up one and try again. Thus the sequence numbers would increment at different intervals but on decoding we can simply take all the packets, order them ascending by sequence number and off we go. It's not like we have to worry about looking for missing packets (bitcoin should never 'drop' a signatory (ie packet) from a multisig output) and we thus only use valid keys and remove this particular censorship vector.
As I say, ugly & a last resort (not least because it shrinks our available number of packets) but thought I'd throw it out there, especially since we're limited to 2 data packets at the moment anyway (M of N with the reference client is limited to N=3 right now I think).
Thanks!
EDIT: for clarity
Considering this further, a cleaner approach would be to reserve the last byte of the compressed public key as disposable data. From my testing, by manipulating the last byte we can get any sequence number into a key that's also ECDSA valid. It doesn't seem to be very compute expensive as we're only testing at worst 255 iterations - in testing the most I found necessary was 5 though I've only had time to do very limited testing.
I'd like to propose the following amendment to multisig to solve the ECDSA point validity issue (hope you don't mind me using your visualization Tachikoma
):
If we take Tachikoma's first example key 020100000014000000020000000005f5e10000000000000f424006000000000001, let's pop off the last byte as that is now reserved (that byte would begin the next packet) so we now have 020100000014000000020000000005f5e10000000000000f4240060000000000 and a byte to do with as we like.
By manipulating the last byte, we can use whatever sequence number we like and still turn them all into valid keys - the below are all (I believe) valid ECDSA points (as you can see we don't have to work very hard to find a byte that does the job)
020100000014000000020000000005f5e10000000000000f424006000000000000
020200000014000000020000000005f5e10000000000000f424006000000000002
020300000014000000020000000005f5e10000000000000f424006000000000001
020400000014000000020000000005f5e10000000000000f424006000000000001
020500000014000000020000000005f5e10000000000000f424006000000000001
020600000014000000020000000005f5e10000000000000f424006000000000000
020700000014000000020000000005f5e10000000000000f424006000000000001
020800000014000000020000000005f5e10000000000000f424006000000000000
020900000014000000020000000005f5e10000000000000f424006000000000000
021000000014000000020000000005f5e10000000000000f424006000000000000
021100000014000000020000000005f5e10000000000000f424006000000000000
021200000014000000020000000005f5e10000000000000f424006000000000000
021300000014000000020000000005f5e10000000000000f424006000000000001
Let's do the same with the second example key 020286a00000000000000000000000000000000000000000000000000000000000, again that last byte is reserved so we'll take that off which gives us 020286a000000000000000000000000000000000000000000000000000000000. Let's see if playing with the last byte can let us use any sequence number and still have valid ECDSA points:
020186a00000000000000000000000000000000000000000000000000000000000
020286a00000000000000000000000000000000000000000000000000000000005
020386a00000000000000000000000000000000000000000000000000000000000
020486a00000000000000000000000000000000000000000000000000000000000
020586a00000000000000000000000000000000000000000000000000000000001
020686a00000000000000000000000000000000000000000000000000000000000
020786a00000000000000000000000000000000000000000000000000000000000
020886a00000000000000000000000000000000000000000000000000000000000
020986a00000000000000000000000000000000000000000000000000000000001
021086a00000000000000000000000000000000000000000000000000000000000
021186a00000000000000000000000000000000000000000000000000000000001
021286a00000000000000000000000000000000000000000000000000000000002
021386a00000000000000000000000000000000000000000000000000000000001
Again I believe those are all valid ECDSA points.
This would obviously need further testing, I'll put together some code to generate a bunch of different mastercoin data pubkeys and then run them against ECDSA validity checks while manipulating the last byte.
This would of course be compatible with existing multisig sends as the last byte on them is already just padding.
Feedback/thoughts on this proposed amendment to multisig would be most welcome.
Thanks!
EDIT: I've written the above primarily discussing sequence numbers as that was the context of the discussion, but it's worth noting that data throughout the key (not just sequence numbers) influences ECDSA point validity, and this last byte technique
should allow us to make any of the varying mastercoin pubkeys we create ECDSA valid.