Provide ECMA5 setters for Address

This commit is contained in:
Kagami Hiiragi 2015-01-18 19:38:23 +03:00
parent 76cf227513
commit 0cd386d65c
2 changed files with 99 additions and 55 deletions

View File

@ -23,21 +23,14 @@ function Address(opts) {
if (!(this instanceof Address)) {
return new Address(opts);
}
opts = opts || {};
objectAssign(this, opts);
this.version = this.version || 4;
opts = objectAssign({}, opts);
// Pull out version right away because it may be needed in setters.
this.version = popkey(opts, "version") || 4;
assert(this.version <= 4, "Version too high");
assert(this.version >= 1, "Version too low");
this.stream = this.stream || 1;
if (this.ripe) {
assertripelen(getripelen(this.ripe), this.version, this.ripe);
if (this.ripe.length < 20) {
var fullripe = new Buffer(20);
fullripe.fill(0);
this.ripe.copy(fullripe, 20 - this.ripe.length);
this.ripe = fullripe;
}
}
this.stream = popkey(opts, "stream") || 1;
// Merge remained values.
objectAssign(this, opts);
}
/**
@ -80,46 +73,16 @@ function getaddrchecksum(data) {
return bmcrypto.sha512(bmcrypto.sha512(data)).slice(0, 4);
}
// Get RIPEMD160(SHA512(SIGN_PUBLIC_KEY || ENC_PUBLIC_KEY)).
// Arguments could be either private or public keys. Private keys are
// **always** 32 bytes in length.
function keys2ripe(signKey, encKey) {
var signPublicKey, encPublicKey;
if (signKey.length === 32) {
signPublicKey = bmcrypto.getPublic(signKey);
} else {
signPublicKey = signKey;
}
if (encKey.length === 32) {
encPublicKey = bmcrypto.getPublic(encKey);
} else {
encPublicKey = encKey;
}
var dataToHash = Buffer.concat([signPublicKey, encPublicKey]);
return bmcrypto.ripemd160(bmcrypto.sha512(dataToHash));
}
/**
* Calculate the ripe hash of the address.
* @param {?Object} opts - Options
* @return {Buffer} Resulting ripe hash.
*/
Address.prototype.getRipe = function(opts) {
var ripe;
opts = opts || {};
if (this.ripe) {
ripe = this.ripe;
} else {
var signKey = this.signPrivateKey || this.signPublicKey;
assert(signKey, "No signing key");
var encKey = this.encPrivateKey || this.encPublicKey;
assert(encKey, "No encryption key");
ripe = keys2ripe(signKey, encKey);
}
var ripelen = getripelen(ripe);
assertripelen(ripelen, this.version, ripe);
var ripe = this.ripe;
if (opts.short) {
return ripe.slice(20 - ripelen);
return ripe.slice(20 - getripelen(ripe));
} else {
return ripe;
}
@ -231,13 +194,8 @@ Address.fromRandom = function(opts) {
ripe = bmcrypto.ripemd160(bmcrypto.sha512(keysbuf));
len = getripelen(ripe);
if (len <= ripelen && checkripelen(len, version)) {
// TODO(Kagami): Do we need to put all these properties or compute
// them manually via ECMA5 getters/setters instead?
opts.signPrivateKey = signPrivateKey;
opts.signPublicKey = signPublicKey;
opts.encPrivateKey = encPrivateKey;
opts.encPublicKey = encPublicKey;
opts.ripe = ripe;
return new Address(opts);
}
}
@ -280,13 +238,8 @@ Address.fromPassphrase = function(opts) {
ripe = bmcrypto.ripemd160(bmcrypto.sha512(keysbuf));
len = getripelen(ripe);
if (len <= ripelen && checkripelen(len, version)) {
// TODO(Kagami): Do we need to put all these properties or compute
// them manually via ECMA5 getters/setters instead?
opts.signPrivateKey = signPrivateKey;
opts.signPublicKey = signPublicKey;
opts.encPrivateKey = encPrivateKey;
opts.encPublicKey = encPublicKey;
opts.ripe = ripe;
return new Address(opts);
}
signnonce += 2;
@ -294,4 +247,81 @@ Address.fromPassphrase = function(opts) {
}
};
Object.defineProperty(Address.prototype, "signPrivateKey", {
get: function() {
return this._signPrivateKey;
},
set: function(signPrivateKey) {
this._signPrivateKey = signPrivateKey;
// Invalidate cached values;
delete this._signPublicKey;
delete this._ripe;
},
});
Object.defineProperty(Address.prototype, "signPublicKey", {
get: function() {
if (this._signPublicKey) {
return this._signPublicKey;
} else if (this.signPrivateKey) {
this._signPublicKey = bmcrypto.getPublic(this.signPrivateKey);
return this._signPublicKey;
} else {
throw new Error("No signing key");
}
},
set: function(signPublicKey) {
this._signPublicKey = signPublicKey;
},
});
Object.defineProperty(Address.prototype, "encPrivateKey", {
get: function() {
return this._encPrivateKey;
},
set: function(encPrivateKey) {
this._encPrivateKey = encPrivateKey;
// Invalidate cached values;
delete this._encPublicKey;
delete this._ripe;
},
});
Object.defineProperty(Address.prototype, "encPublicKey", {
get: function() {
if (this._encPublicKey) {
return this._encPublicKey;
} else if (this.encPrivateKey) {
this._encPublicKey = bmcrypto.getPublic(this.encPrivateKey);
return this._encPublicKey;
} else {
throw new Error("No encryption key");
}
},
set: function(encPublicKey) {
this._encPublicKey = encPublicKey;
},
});
Object.defineProperty(Address.prototype, "ripe", {
get: function() {
if (this._ripe) {
return this._ripe;
}
var dataToHash = Buffer.concat([this.signPublicKey, this.encPublicKey]);
this._ripe = bmcrypto.ripemd160(bmcrypto.sha512(dataToHash));
return this._ripe;
},
set: function(ripe) {
assertripelen(getripelen(ripe), this.version, ripe);
if (ripe.length < 20) {
var fullripe = new Buffer(20);
fullripe.fill(0);
ripe.copy(fullripe, 20 - ripe.length);
ripe = fullripe;
}
this._ripe = ripe;
},
});
module.exports = Address;

14
test.js
View File

@ -581,6 +581,20 @@ describe("High-level classes", function() {
expect(Address.decode(addr)).to.equal(addr);
});
it("should provide setters for keys and ripe", function() {
var addr = Address();
expect(function(){addr.ripe}).to.throw(Error);
addr.signPrivateKey = Buffer("71c95d26c716a5e85e9af9efe26fb5f744dc98005a13d05d23ee92c77e038d9f", "hex");
expect(addr.signPublicKey.toString("hex")).to.equal("042d391543f574608cbcdfd12a37cc4c74dd36e54510b13a6a1d8b7b1498fb96c92873d33ca17586dace7f5ad0f4532a954061ac06bc5230aed9c8374072546571");
expect(function(){addr.ripe}).to.throw(Error);
addr.encPrivateKey = Buffer("9f9969c93c2d186787a7653f70e49be34c03c4a853e6ad0c867db0946bc433c6", "hex");
expect(addr.encPublicKey.toString("hex")).to.equal("04c6ed1b56f2da97fec1b762d43364566faf082c1e4918ae1dbb41757cad41b03b2cc5087f341414e63f6eee72a1fbf0b5f346a1bb3ba944cad204ca597db2bfc8");
expect(addr.ripe.toString("hex")).to.equal("003ab6655de4bd8c603eba9b00dd5970725fdd56");
expect(addr.getRipe({short: true}).toString("hex")).to.equal("3ab6655de4bd8c603eba9b00dd5970725fdd56");
addr.encPrivateKey = Buffer("009969c93c2d186787a7653f70e49be34c03c4a853e6ad0c867db0946bc433c6", "hex");
expect(addr.getRipe({short: true}).toString("hex")).to.equal("69617ddb1946dc327cadffcf33889fed587fc1e7");
});
// FIXME(Kagami): Don't run it in browser currently because it's
// very slow. This need to be fixed.
if (allTests && typeof window === "undefined") {