Skip to content

Commit

Permalink
Merge branch account-ids
Browse files Browse the repository at this point in the history
  • Loading branch information
wltsmrz committed May 15, 2014
1 parent 9025119 commit 8979a3c
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 12 deletions.
56 changes: 44 additions & 12 deletions src/js/ripple/seed.js
Expand Up @@ -11,6 +11,7 @@ var BigInteger = utils.jsbn.BigInteger;
var Base = require('./base').Base;
var UInt = require('./uint').UInt;
var UInt256 = require('./uint256').UInt256;
var UInt160 = require('./uint160').UInt160;
var KeyPair = require('./keypair').KeyPair;

var Seed = extend(function () {
Expand Down Expand Up @@ -83,16 +84,33 @@ function SHA256_RIPEMD160(bits) {
return sjcl.hash.ripemd160.hash(sjcl.hash.sha256.hash(bits));
};

Seed.prototype.get_key = function (account_id) {
/**
* @param account
* {undefined} take first, default, KeyPair
*
* {Number} specifies the account number of the KeyPair
* desired.
*
* {Uint160} (from_json able), specifies the address matching the KeyPair
* that is desired.
*/
Seed.prototype.get_key = function (account) {
var account_number = 0, address;

if (!this.is_valid()) {
throw new Error('Cannot generate keys from invalid seed!');
}

// XXX Should loop over keys until we find the right one
if (account) {
if (typeof account === 'number') {
account_number = account;
} else {
address = UInt160.from_json(account);
}
}

var private_gen, public_gen;
var curve = this._curve;
var seq = 0, i = 0;
var i = 0;

do {
private_gen = sjcl.bn.fromBits(firstHalfOfSHA512(append_int(this.to_bytes(), i)));
Expand All @@ -102,16 +120,30 @@ Seed.prototype.get_key = function (account_id) {
public_gen = curve.G.mult(private_gen);

var sec;
i = 0;
var key_pair;
var max_loops = 1000; // TODO

do {
sec = sjcl.bn.fromBits(firstHalfOfSHA512(append_int(append_int(public_gen.toBytesCompressed(), seq), i)));
i++;
} while (!curve.r.greaterEquals(sec));

sec = sec.add(private_gen).mod(curve.r);

return KeyPair.from_bn_secret(sec);
i = 0;

do {
sec = sjcl.bn.fromBits(firstHalfOfSHA512(append_int(append_int(public_gen.toBytesCompressed(), account_number), i)));
i++;
} while (!curve.r.greaterEquals(sec));

account_number++;
sec = sec.add(private_gen).mod(curve.r);
key_pair = KeyPair.from_bn_secret(sec);

if (--max_loops <= 0) {
// We are almost certainly looking for an account that would take same
// value of $too_long {forever, ...}
throw new Error('Too many loops looking for KeyPair yielding '+
address.to_json() +' from ' + this.to_json());
};
} while (address && !key_pair.get_address().equals(address));

return key_pair;
};

exports.Seed = Seed;
63 changes: 63 additions & 0 deletions test/seed-test.js
@@ -0,0 +1,63 @@
var assert = require('assert');
var utils = require('./testutils');
var Seed = utils.load_module('seed').Seed;
var config = require('./testutils').get_config();

describe('Seed', function() {
it('can generate many addresses', function () {
var seed = Seed.from_json("masterpassphrase");

// Note: Created with jRippleAPI code
// Link: https://github.com/pmarches/jRippleAPI/blob/master/src/jrippleapi/keys/RippleDeterministicKeyGenerator.java

// To reviewer/merger: Even generating keypairs for thi this small amount of
// addresses makes the test suite run SO SLOW. Consider cutting at the tail.
var first_nth_addresses = [
// 0th implied
"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
// 1th implied
"r4bYF7SLUMD7QgSLLpgJx38WJSY12ViRjP",
// 2th implied
"rLpAd4peHUMBPbVJASMYK5GTBUSwXRD9nx",
// ...
"rN9HWHPAftXC6xNxJRqgVr1HexpUi6FBUa",
"rhwPfeEkeQh2vqoKGPBpPyS9nKmKZdpypu",
"rKdNfPfrzfisDCPCqK67YhDLezuVKGKXNm",
"rsn4NeGzMRvMn5ABQxmt9VNEkSknVneBK4",
"rUSJGFH1kQnaKpoAhkArfyw6HZVe8GT5w3",
"r3EYp6isx2Row5pu19C4Ujvp68oEEabhuA",
"rGiYpnAn9DTXiM78CCJcYAuL6QHEDdazHA",
"rVrRVeqqEJHAove5B9TqBAHEXBTzMi5eu",
"rJbarThDXYXxtCgDxRoTCDf2NoYdgSjuVk",
"rfuWNJ1TkQzoZZcc4K8wmtsUiGwURFbed1",
"rpuTqebfbZZdKEUV3bjecoViNL4W4gepWZ",
"r42ywHUco4C2AjgaSmYM7uX13Kbz6GdDKp",
"rnWb45MLd5hQiB6Arr94DdY2z95quL7XNf",
"rMukaQ87bfAeddcT16RtgS3RbFmaQWrSGu",
"rN6dMHU51K9y8eVMhjQMsQVp5gPwt3eYYx",
"rfRFyeJDNqpfZVFmjNj9tNzFVsCNAWKtNc",
"rMoGSX48KrT31HKx9KfMSnYhjvRw3YYzQW",
"rfTiEfbeVsYU7QEe1Zfogiz7h43x6ChKGC"
]

function assert_helper(account_id, expected) {
var keypair = seed.get_key(account_id);
assert.strictEqual(keypair.get_address().to_json(),
expected);
}
for (var nth = 0; nth < first_nth_addresses.length; nth++) {
var expected = first_nth_addresses[nth], looking_for;

//`seed.get_key($ripple_address)` is arguably an ill concieved feature
// as it needs to generate `nth` many keypairs and generate hashed public
// keys (addresses) for equality tests ??
// Would need remote.set_secret(address, private_key_not_seed) ??
assert_helper((looking_for = expected), expected)

// This isn't too bad as it only needs to generate one keypair `seq`
assert_helper((looking_for = nth), expected)
};
});
});

// vim:sw=2:sts=2:ts=8:et

2 comments on commit 8979a3c

@sublimator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, interesting, I don't know this commit actually bought anything either, just by itself.

https://github.com/ripple/ripple-lib/blob/develop/src/js/ripple/transaction.js#L306
You could change that line to pass undefined to restore the old behavior.

@sublimator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.