verificationError = function(hashbuf, sig, pubkey, opts) {
  const { endian = 'big' } = opts || {};

  if (!BufferUtil.isBuffer(hashbuf) || hashbuf.length !== 32) {
    return 'hashbuf must be a 32 byte buffer';
  }

  var r = sig.r;
  var s = sig.s;
  if (!(r.gt(BN.Zero) && r.lt(Point.getN())) || !(s.gt(BN.Zero) && s.lt(Point.getN()))) {
    return 'r and s not in range';
  }

  var e = BN.fromBuffer(hashbuf, { endian });
  var n = Point.getN();
  var sinv = s.invm(n);
  var u1 = sinv.mul(e).umod(n);
  var u2 = sinv.mul(r).umod(n);

  var p = Point.getG().mulAdd(u1, pubkey.point, u2);
  if (p.isInfinity()) {
    return 'p is infinity';
  }

  if (p.getX().umod(n).cmp(r) !== 0) {
    return 'Invalid signature';
  }

  return; // no error
}
Get signature verification error string
@param {Buffer} hashbuf
@param {Signature} sig
@param {PublicKey} pubkey
@param {Object|undefined} opts An object of optional parameters
@param {String} opts.endian 'big' or 'little' (default: big)
@returns {String|undefined} Returns an error string, or undefined if there is no error