itns-sidechain/lib/script/sigcache.js

159 lines
2.8 KiB
JavaScript
Raw Normal View History

2016-07-02 07:09:22 -07:00
/*!
2018-08-01 20:00:09 -07:00
* sigcache.js - signature cache for hsd
2018-02-01 13:40:45 -08:00
* Copyright (c) 2017-2018, Christopher Jeffrey (MIT License).
2018-08-01 20:00:09 -07:00
* https://github.com/handshake-org/hsd
2016-07-02 07:09:22 -07:00
*/
'use strict';
2018-07-19 05:40:48 -07:00
const assert = require('bsert');
const {BufferMap} = require('buffer-map');
const secp256k1 = require('bcrypto/lib/secp256k1');
2016-07-02 07:09:22 -07:00
/** @typedef {import('../types').Hash} Hash */
2016-07-02 07:09:22 -07:00
/**
* Signature cache.
2017-02-03 22:47:26 -08:00
* @alias module:script.SigCache
2016-07-02 07:09:22 -07:00
* @property {Number} size
* @property {Hash[]} keys
* @property {Object} valid
*/
2017-11-16 18:44:38 -08:00
class SigCache {
/**
* Create a signature cache.
* @constructor
* @param {Number} [size=10000]
*/
2016-07-02 07:09:22 -07:00
2017-11-16 18:44:38 -08:00
constructor(size) {
if (size == null)
size = 10000;
2016-07-02 07:09:22 -07:00
2017-11-16 18:44:38 -08:00
assert((size >>> 0) === size);
2016-07-02 07:09:22 -07:00
2017-11-16 18:44:38 -08:00
this.size = size;
this.keys = [];
this.valid = new BufferMap();
2017-11-16 18:44:38 -08:00
}
2016-07-29 15:40:39 -07:00
2017-11-16 18:44:38 -08:00
/**
* Resize the sigcache.
* @param {Number} size
*/
2016-07-29 15:40:39 -07:00
2017-11-16 18:44:38 -08:00
resize(size) {
assert((size >>> 0) === size);
2016-07-29 15:40:39 -07:00
2017-11-16 18:44:38 -08:00
this.size = size;
this.keys.length = 0;
this.valid.clear();
}
2016-07-02 07:09:22 -07:00
2017-11-16 18:44:38 -08:00
/**
* Add item to the sigcache.
* Potentially evict a random member.
* @param {Hash} hash - Sig hash.
* @param {Buffer} sig
* @param {Buffer} key
*/
add(hash, sig, key) {
if (this.size === 0)
return;
this.valid.set(hash, new SigCacheEntry(sig, key));
if (this.keys.length >= this.size) {
const i = Math.floor(Math.random() * this.keys.length);
const k = this.keys[i];
this.valid.delete(k);
this.keys[i] = hash;
} else {
this.keys.push(hash);
}
2016-07-02 07:09:22 -07:00
}
2017-11-16 18:44:38 -08:00
/**
* Test whether the sig exists.
* @param {Hash} hash - Sig hash.
* @param {Buffer} sig
* @param {Buffer} key
* @returns {Boolean}
*/
2016-07-02 07:09:22 -07:00
2017-11-16 18:44:38 -08:00
has(hash, sig, key) {
const entry = this.valid.get(hash);
2016-07-02 07:09:22 -07:00
2017-11-16 18:44:38 -08:00
if (!entry)
return false;
2016-07-02 07:09:22 -07:00
2017-11-16 18:44:38 -08:00
return entry.equals(sig, key);
}
2016-07-02 07:09:22 -07:00
2017-11-16 18:44:38 -08:00
/**
* Verify a signature, testing
* it against the cache first.
2024-09-30 14:29:03 +04:00
* @param {Hash} hash
2017-11-16 18:44:38 -08:00
* @param {Buffer} sig
* @param {Buffer} key
* @returns {Boolean}
*/
2016-07-02 07:09:22 -07:00
verify(hash, sig, key) {
2017-11-16 18:44:38 -08:00
if (this.size === 0)
return secp256k1.verify(hash, sig, key);
2016-07-02 07:09:22 -07:00
2017-11-16 18:44:38 -08:00
if (this.has(hash, sig, key))
return true;
2016-07-02 07:09:22 -07:00
const result = secp256k1.verify(hash, sig, key);
2016-07-02 07:09:22 -07:00
2017-11-16 18:44:38 -08:00
if (!result)
return false;
2016-07-02 07:09:22 -07:00
2017-11-16 18:44:38 -08:00
this.add(hash, sig, key);
2016-07-02 07:09:22 -07:00
2017-11-16 18:44:38 -08:00
return true;
}
}
2016-07-02 07:09:22 -07:00
/**
2017-11-16 18:44:38 -08:00
* Signature Cache Entry
2017-02-03 22:47:26 -08:00
* @ignore
2016-07-02 07:09:22 -07:00
* @property {Buffer} sig
* @property {Buffer} key
*/
2017-11-16 18:44:38 -08:00
class SigCacheEntry {
/**
* Create a cache entry.
* @constructor
* @param {Buffer} sig
* @param {Buffer} key
*/
constructor(sig, key) {
this.sig = Buffer.from(sig);
this.key = Buffer.from(key);
}
2016-07-02 07:09:22 -07:00
2017-11-16 18:44:38 -08:00
/**
* Compare an entry to a sig and key.
* @param {Buffer} sig
* @param {Buffer} key
* @returns {Boolean}
*/
2016-07-02 07:09:22 -07:00
2017-11-16 18:44:38 -08:00
equals(sig, key) {
return this.sig.equals(sig) && this.key.equals(key);
}
}
2016-07-02 07:09:22 -07:00
/*
* Expose
*/
2017-06-30 03:03:39 -07:00
module.exports = SigCache;