There are two problems:
- You are verifying the wrong data. use
transaction.hash()
instead of transaction.signatureBase()
. According to the transaction.signatureBase()
docs:
Returns the "signature base" of this transaction, which is the value that, when hashed, should be signed to create a signature that validators on the Stellar Network will accept
- It states in the documentation that the argument is of type
Buffer
and your s
variable is an xdr.DecoratedSignature
. You need to extract the signature buffer inside of it. That is, use s._attributes.signature
instead of just s
(I know this seems hacky, but the SDK doesn't provide a Signature
type, which would probably be more appropriate here)
Your hideous one-liner with these changes:
const bHMainKeys = Keypair.fromSecret(privateKey)
if (transaction.source !== bHMainKeys.publicKey() || !transaction.signatures.some((s) => bHMainKeys.verify(transaction.hash(), s._attributes.signature))) {
return res.status(500).send({ error: 'Invalid Transaction' })
}
Also bear in mind that if the account has other signers, a signature by a different key may be valid on the network. In order to account for this you need to query horizon for the signers on the account, then check if the signature is valid for their keys as well. The javascript SDK does not provide one correct verification method for this. Here's how Stellar Laboratory does it:
https://github.com/stellar/laboratory/blob/4abbd25659c070b88071dfc73513f006e6925b7c/src/actions/xdrViewer.js#L63