UNPKG

know-js

Version:

JavaScript library for sending Know transactions from the client or server

347 lines (276 loc) 11.1 kB
var Buffer = require("buffer/").Buffer; var should = require("should"); var know = require("../../index.js"); describe("transaction.js", function () { var transaction = know.transaction; it("should be object", function () { (transaction).should.be.type("object"); }); it("should have properties", function () { (transaction).should.have.property("createTransaction"); }) describe("#createTransaction", function () { var createTransaction = transaction.createTransaction; var trs = null; it("should be a function", function () { (createTransaction).should.be.type("function"); }); it("should create transaction without second signature", function () { trs = createTransaction("AJWRd23HNEhPLkK1ymMnwnDBX2a7QBZqff", 1000, null, "secret"); (trs).should.be.ok; }); it("should create transaction without second signature from keys", function () { var secretKey = know.ECPair.fromSeed("secret"); secretKey.publicKey = secretKey.getPublicKeyBuffer().toString("hex"); trs = createTransaction("AJWRd23HNEhPLkK1ymMnwnDBX2a7QBZqff", 1000, null, secretKey); (trs).should.be.ok; }); it("should create transaction with vendorField", function () { trs = createTransaction("AJWRd23HNEhPLkK1ymMnwnDBX2a7QBZqff", 1000, "this is a test vendorfield", "secret"); (trs).should.be.ok; }); it("should create transaction with fee override", function () { const feeOverride = 1000000 trs = createTransaction("AJWRd23HNEhPLkK1ymMnwnDBX2a7QBZqff", 1000, null, "secret", undefined, undefined, feeOverride); (trs).should.be.ok; (trs.fee).should.equal(feeOverride) }); it("should fail to create transaction with invalid fee override", function (done) { const feeOverride = '1000000' try { trs = createTransaction("AJWRd23HNEhPLkK1ymMnwnDBX2a7QBZqff", 1000, null, "secret", undefined, undefined, feeOverride); should.fail() } catch (error) { done() } }); it("should fail if transaction with vendorField length > 64", function () { var vf="z"; for(i=0;i<6;i++){ vf=vf+vf; } vf=vf+"z"; trs = createTransaction("AJWRd23HNEhPLkK1ymMnwnDBX2a7QBZqff", 1000, vf, "secret"); return (trs===null).should.equal(true); }); it("should be ok if transaction with vendorField length = 64", function () { var vf="z"; for(i=0;i<6;i++){ vf=vf+vf; } trs = createTransaction("AJWRd23HNEhPLkK1ymMnwnDBX2a7QBZqff", 1000, vf, "secret"); (trs).should.be.ok; }); describe("returned transaction", function () { it("should be object", function () { (trs).should.be.type("object"); }); it("should have id as string", function () { (trs.id).should.be.type("string"); }); it("should have type as number and eqaul 0", function () { (trs.type).should.be.type("number").and.equal(0); }); it("should have timestamp as number", function () { (trs.timestamp).should.be.type("number").and.not.NaN; }); it("should have senderPublicKey as hex string", function () { (trs.senderPublicKey).should.be.type("string").and.match(function () { try { new Buffer(trs.senderPublicKey, "hex") } catch (e) { return false; } return true; }) }); it("should have recipientId as string and to be equal AJWRd23HNEhPLkK1ymMnwnDBX2a7QBZqff", function () { (trs.recipientId).should.be.type("string").and.equal("AJWRd23HNEhPLkK1ymMnwnDBX2a7QBZqff"); }); it("should have amount as number and eqaul to 1000", function () { (trs.amount).should.be.type("number").and.equal(1000); }); it("should have empty asset object", function () { (trs.asset).should.be.type("object").and.empty; }); it("should does not have second signature", function () { (trs).should.not.have.property("signSignature"); }); it("should have signature as hex string", function () { (trs.signature).should.be.type("string").and.match(function () { try { new Buffer(trs.signature, "hex") } catch (e) { return false; } return true; }) }); it("should be signed correctly", function () { var result = know.crypto.verify(trs); result.should.equal(true); }); it("should be deserialised correctly", function () { var deserialisedTx = know.crypto.fromBytes(know.crypto.getBytes(trs).toString("hex")); deserialisedTx.vendorField = new Buffer(deserialisedTx.vendorFieldHex, "hex").toString("utf8") delete deserialisedTx.vendorFieldHex; var keys = Object.keys(deserialisedTx) for(key in keys){ if(keys[key] != "vendorFieldHex"){ deserialisedTx[keys[key]].should.equal(trs[keys[key]]); } } }); it("should not be signed correctly now", function () { trs.amount = 10000; var result = know.crypto.verify(trs); result.should.equal(false); }); }); }); describe("createTransaction and try to tamper signature", function(){ it("should not validate overflown signatures", function(){ var BigInteger = require('bigi') var bip66 = require('bip66') // custom bip66 encode for hacking away signature function BIP66_encode (r, s) { var lenR = r.length; var lenS = s.length; var signature = new Buffer(6 + lenR + lenS); // 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] signature[0] = 0x30; signature[1] = signature.length - 2; signature[2] = 0x02; signature[3] = r.length; r.copy(signature, 4); signature[4 + lenR] = 0x02; signature[5 + lenR] = s.length; s.copy(signature, 6 + lenR); return signature; } // The transaction to replay var old_transaction = know.transaction.createTransaction('AacRfTLtxAkR3Mind1XdPCddj1uDkHtwzD', 1, null, 'randomstring'); // Decode signature var decode = bip66.decode(Buffer(old_transaction.signature, "hex")); var r = BigInteger.fromDERInteger(decode.r); var s = BigInteger.fromDERInteger(decode.s); // Transform the signature /* result = r|00 result = result - r r = r + result */ result = BigInteger.fromBuffer(Buffer(r.toBuffer(r.toDERInteger().length).toString('hex') + '06', 'hex')); result = result.subtract(r); r = r.add(result); new_signature = BIP66_encode(r.toBuffer(r.toDERInteger().length), s.toBuffer(s.toDERInteger().length)).toString('hex'); // know.crypto.verify(old_transaction).should.equal(true); old_transaction.signature = new_signature; know.crypto.verify(old_transaction).should.equal(false); }); }); describe("#createTransaction with second secret", function () { var createTransaction = transaction.createTransaction; var trs = null; var secondSecret = "second secret"; var keys = know.crypto.getKeys(secondSecret); it("should be a function", function () { (createTransaction).should.be.type("function"); }); it("should not accept bitcoin address", function(){ try { trs = createTransaction("14owCmVDn8SaAFZcLbZfCVu5jvc4Lq7Tm1", 1000, null, "secret", secondSecret); } catch(error){ return (error).should.have.property("message").and.equal("Wrong recipientId") } true.should.equal(false); }); it("should create transaction without second signature", function () { trs = createTransaction("AJWRd23HNEhPLkK1ymMnwnDBX2a7QBZqff", 1000, null, "secret", secondSecret); (trs).should.be.ok; }); describe("returned transaction", function () { it("should be object", function () { (trs).should.be.type("object"); }); it("should have id as string", function () { (trs.id).should.be.type("string"); }); it("should have type as number and eqaul 0", function () { (trs.type).should.be.type("number").and.equal(0); }); it("should have timestamp as number", function () { (trs.timestamp).should.be.type("number").and.not.NaN; }); it("should have senderPublicKey as hex string", function () { (trs.senderPublicKey).should.be.type("string").and.match(function () { try { new Buffer(trs.senderPublicKey, "hex") } catch (e) { return false; } return true; }) }); it("should have recipientId as string and to be equal AJWRd23HNEhPLkK1ymMnwnDBX2a7QBZqff", function () { (trs.recipientId).should.be.type("string").and.equal("AJWRd23HNEhPLkK1ymMnwnDBX2a7QBZqff"); }); it("should have amount as number and eqaul to 1000", function () { (trs.amount).should.be.type("number").and.equal(1000); }); it("should have empty asset object", function () { (trs.asset).should.be.type("object").and.empty; }); it("should have second signature", function () { (trs).should.have.property("signSignature"); }); it("should have signature as hex string", function () { (trs.signature).should.be.type("string").and.match(function () { try { new Buffer(trs.signature, "hex") } catch (e) { return false; } return true; }) }); it("should have signSignature as hex string", function () { (trs.signSignature).should.be.type("string").and.match(function () { try { new Buffer(trs.signSignature, "hex"); } catch (e) { return false; } return true; }); }); it("should be deserialised correctly", function () { var deserialisedTx = know.crypto.fromBytes(know.crypto.getBytes(trs).toString("hex")); delete deserialisedTx.vendorFieldHex; var keys = Object.keys(deserialisedTx) for(key in keys){ deserialisedTx[keys[key]].should.equal(trs[keys[key]]); } }); it("should be signed correctly", function () { var result = know.crypto.verify(trs); (result).should.equal(true); }); it("should be second signed correctly", function () { var result = know.crypto.verifySecondSignature(trs, keys.publicKey); (result).should.equal(true); }); it("should not be signed correctly now", function () { trs.amount = 10000; var result = know.crypto.verify(trs); (result).should.equal(false); }); it("should not be second signed correctly now", function () { trs.amount = 10000; var result = know.crypto.verifySecondSignature(trs, keys.publicKey); (result).should.equal(false); }); }); }); });