forked from bitpay/bitcore
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'bws-doge-ltc-chaintests' of https://github.com/clabby/b…
- Loading branch information
Showing
2 changed files
with
631 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,325 @@ | ||
'use strict'; | ||
|
||
const _ = require('lodash'); | ||
const chai = require('chai'); | ||
const should = chai.should(); | ||
const { BitcoreLibDoge } = require ('crypto-wallet-core'); | ||
const { ChainService } = require('../../ts_build/lib/chain'); | ||
const { DogeChain } = require('../../ts_build/lib/chain/doge'); | ||
const { TxProposal } = require('../../ts_build/lib/model/txproposal'); | ||
|
||
const Common = require('../../ts_build/lib/common'); | ||
const Constants = Common.Constants; | ||
|
||
describe('Chain DOGE', () => { | ||
describe('#getBitcoreTx', () => { | ||
it('should create a valid bitcore TX', () => { | ||
const txp = TxProposal.fromObj(aTXP()); | ||
const t = ChainService.getBitcoreTx(txp); | ||
should.exist(t); | ||
}); | ||
it('should order outputs as specified by outputOrder', () => { | ||
const txp = TxProposal.fromObj(aTXP()); | ||
|
||
txp.outputOrder = [0, 1, 2]; | ||
const t = ChainService.getBitcoreTx(txp); | ||
t.getChangeOutput().should.deep.equal(t.outputs[2]); | ||
|
||
txp.outputOrder = [2, 0, 1]; | ||
const t2 = ChainService.getBitcoreTx(txp); | ||
t2.getChangeOutput().should.deep.equal(t2.outputs[0]); | ||
}); | ||
|
||
it('should create a valid signed bitcore TX', () => { | ||
const txp = TxProposal.fromObj(signedTxp); | ||
const t = ChainService.getBitcoreTx(txp); | ||
should.exist(t); | ||
|
||
// should serialized | ||
t.serialize().should.equal('0100000001b8a1d4773add3d5ca38652537310e9bd64d812d771e16f62b4a6e33e79f85453000000006b483045022100a9bee101f13eeb8f6bdf1b6421974a17b2aeb0bcf080526df20e93483a67bbca022071ba69e707430136fb65488b1e5413eb54279770b74b7e15fe15aeac16770ceb012102f4526941f57f37b8f1cd4970091ebcd1701980a82d26a781b2e44b384609eb22ffffffff026c81c9f6160900001976a914aeb332ea003a7efb5dab0dcc56d19fed84e26afb88acf4cb5156010000001976a914afbf96bfb28815cad8205c8f2f5a86819136664c88ac00000000'); | ||
t.isFullySigned().should.equal(true); | ||
}); | ||
|
||
it('should create a valid unsigned bitcore TX', () => { | ||
const txp = TxProposal.fromObj(signedTxp); | ||
const t = ChainService.getBitcoreTx(txp, { signed: false } ); | ||
should.exist(t); | ||
|
||
// should serialized | ||
(() => { return t.serialize(); }).should.throw('not been fully signed'); | ||
|
||
t.uncheckedSerialize().should.equal('0100000001b8a1d4773add3d5ca38652537310e9bd64d812d771e16f62b4a6e33e79f854530000000000ffffffff026c81c9f6160900001976a914aeb332ea003a7efb5dab0dcc56d19fed84e26afb88acf4cb5156010000001976a914afbf96bfb28815cad8205c8f2f5a86819136664c88ac00000000'); | ||
t.isFullySigned().should.equal(false); | ||
}); | ||
}); | ||
|
||
describe('#getEstimatedSize', () => { | ||
let doge, fromAddress, simpleUtxo, changeAddress, toAddress, privateKey; | ||
|
||
before(() => { | ||
doge = new DogeChain(); | ||
fromAddress = 'D9w9sRrMYictva4me78h3EsivKdsYUffY3'; | ||
toAddress = 'DCcS6pGDLUfXZSxQEMKJgmBjYNRcW4wuo4'; | ||
changeAddress = 'D7J3Mqji3bfPKMXoSmaCQtk7nhLULaNmUM'; | ||
privateKey = 'QWL2M3x4s8LVroDNZu3jFnWmTSVDL8RtgKvc7Uj1VasHdPeisD1o'; | ||
simpleUtxo = { | ||
address: fromAddress, | ||
txId: '0820f0d4aafe9f142d18c6400ed3d58af5f0834b4b05ae41b3adbef61d6b7e1b', | ||
outputIndex: 0, | ||
script: BitcoreLibDoge.Script.buildPublicKeyHashOut(fromAddress).toString(), | ||
satoshis: 1e9, | ||
}; | ||
|
||
const privKey = new BitcoreLibDoge.PrivateKey(); | ||
}); | ||
|
||
it('1 input p2pkh,1 output p2pkh: Margin should be 10%', () => { | ||
let x = TxProposal.fromObj(aTXP()); | ||
delete x.changeAddress; | ||
x.outputs.pop(); | ||
x.addressType = Constants.SCRIPT_TYPES.P2PKH; | ||
const estimatedLength = doge.getEstimatedSize(x); | ||
|
||
// Create a similar TX. | ||
let tx = new BitcoreLibDoge.Transaction(); | ||
tx.from(simpleUtxo) | ||
.to([{ address: toAddress, satoshis: 1e9 - 1e8 }]) | ||
.sign(privateKey); | ||
|
||
const actualLength = tx.serialize().length/2; | ||
|
||
// Check margin is ~0.0 | ||
((Math.abs(actualLength-estimatedLength))/actualLength).should.not.be.above(0.05); | ||
}); | ||
|
||
const p2shPrivateKey1 = BitcoreLibDoge.PrivateKey.fromWIF('QQu6YLUqhPdHSGDyPWk1nB3225NTpMg9HE6eecFmE4169dTjtxjX'); | ||
const p2shPublicKey1 = p2shPrivateKey1.toPublicKey(); | ||
const p2shPrivateKey2 = BitcoreLibDoge.PrivateKey.fromWIF('QQrWAEuSPk8TZF9rakoHGNiKmmhzshSEYkRp2J59TrhCXTkraP65'); | ||
const p2shPublicKey2 = p2shPrivateKey2.toPublicKey(); | ||
|
||
const p2shAddress = BitcoreLibDoge.Address.createMultisig([ | ||
p2shPublicKey1, | ||
p2shPublicKey2, | ||
], 2, 'testnet'); | ||
const p2shUtxoWithDOGE = { | ||
address: p2shAddress.toString(), | ||
txId: '0820f0d4aafe9f142d18c6400ed3d58af5f0834b4b05ae41b3adbef61d6b7e1b', | ||
outputIndex: 0, | ||
script: BitcoreLibDoge.Script(p2shAddress).toString(), | ||
satoshis: 3e9 | ||
}; | ||
|
||
it('1 input p2sh, 2 P2PKH outputs: ', () => { | ||
let x = TxProposal.fromObj(aTXP()); | ||
|
||
// Create a similar TX. | ||
let tx = new BitcoreLibDoge.Transaction(); | ||
tx.from(p2shUtxoWithDOGE, [p2shPublicKey1, p2shPublicKey2], 2) | ||
.to([{ address: toAddress, satoshis: 1e9 }, { address: toAddress, satoshis: 2e8 }]) | ||
.change(changeAddress) | ||
.sign(p2shPrivateKey1) | ||
.sign(p2shPrivateKey2); | ||
const estimatedLength = doge.getEstimatedSize(x); | ||
|
||
const actualLength = tx.serialize().length / 2; | ||
((Math.abs(actualLength-estimatedLength))/actualLength).should.be.below(0.05); | ||
}); | ||
|
||
it('1 input p2wpkh, 1 Native Segwit output: ', () => { | ||
let x = TxProposal.fromObj(aTXP()); | ||
|
||
// just to force the desired calculation | ||
x.addressType = Constants.SCRIPT_TYPES.P2WPKH; | ||
|
||
x.outputs[0].toAddress = 'DGMBDFnEDepajnZZNS8F6WC3BjTLMyaLCo'; | ||
x.outputs.pop(); | ||
delete x.changeAddress; | ||
const estimatedLength = doge.getEstimatedSize(x); | ||
|
||
// https://bitcoin.stackexchange.com/questions/84004/how-do-virtual-size-stripped-size-and-raw-size-compare-between-legacy-address-f | ||
const actualLength = 437 / 4; // this is the vsize | ||
((Math.abs(actualLength-estimatedLength))/actualLength).should.be.below(0.05); | ||
}); | ||
|
||
it('2 input multisig p2wsh, 1 native segwit output: ', () => { | ||
let x = TxProposal.fromObj(aTXP()); | ||
x.addressType = Constants.SCRIPT_TYPES.P2WSH; | ||
x.outputs[0].toAddress = toAddress; | ||
delete x.changeAddress; | ||
x.outputs.pop(); | ||
const estimatedLength = doge.getEstimatedSize(x); | ||
|
||
// from https://bitcoin.stackexchange.com/questions/88226/how-to-calculate-the-size-of-multisig-transaction | ||
const actualLength = (346 + 2 * 108) / 4; // this is the vsize | ||
((Math.abs(actualLength-estimatedLength))/actualLength).should.be.below(0.05); | ||
}); | ||
}); | ||
}); | ||
|
||
const aTXP = () => { | ||
const txp = { | ||
'version': 3, | ||
'createdOn': 1423146231, | ||
'id': '75c34f49-1ed6-255f-e9fd-0c71ae75ed1e', | ||
'walletId': '1', | ||
'creatorId': '1', | ||
'coin': 'doge', | ||
'network': 'livenet', | ||
'amount': 1.2550574e14, | ||
'message': 'some message', | ||
'proposalSignature': '304402207e8ba2f9e88c1e7a76979f7e9df4d1cf43784d196b4b92f7f605386d0562216c022025356aae37397771a5fcb7520e97096fed197598a0e68883f6b30f3ccddd636c', | ||
'changeAddress': { | ||
'version': '1.0.0', | ||
'createdOn': 1424372337, | ||
'address': 'D7J3Mqji3bfPKMXoSmaCQtk7nhLULaNmUM', | ||
'path': 'm/2147483647/1/0', | ||
'publicKeys': [ | ||
'030562cb099e6043dc499eb359dd97c9d500a3586498e4bcf0228a178cc20e6f16', | ||
'0367027d17dbdfc27b5e31f8ed70e14d47949f0fa392261e977db0851c8b0d6fac', | ||
'0315ae1e8aa866794ae603389fb2b8549153ebf04e7cdf74501dadde5c75ddad11' | ||
] | ||
}, | ||
'inputs': [ | ||
{ | ||
'txid': '0820f0d4aafe9f142d18c6400ed3d58af5f0834b4b05ae41b3adbef61d6b7e1b', | ||
'vout': 8, | ||
'satoshis': 1.2550574e14, | ||
'scriptPubKey': 'a914a8a9648754fbda1b6c208ac9d4e252075447f36887', | ||
'address': 'D9w9sRrMYictva4me78h3EsivKdsYUffY3', | ||
'path': 'm/2147483647/0/1', | ||
'publicKeys': [ | ||
'0319008ffe1b3e208f5ebed8f46495c056763f87b07930a7027a92ee477fb0cb0f', | ||
'03b5f035af8be40d0db5abb306b7754949ab39032cf99ad177691753b37d101301' | ||
] | ||
} | ||
], | ||
'inputPaths': ['m/2147483647/0/1'], | ||
'requiredSignatures': 2, | ||
'requiredRejections': 1, | ||
'walletN': 2, | ||
'addressType': 'P2SH', | ||
'status': 'pending', | ||
'actions': [], | ||
'fee': 665600000, | ||
'outputs': [ | ||
{ | ||
'toAddress': 'DKdkvdJfQwQmnT9Hvq1CdB9kzsy76f1Qsd', | ||
'amount': 77700000000000, | ||
'message': 'first message' | ||
}, { | ||
'toAddress': 'DL2EGukahtib57Sg7FtHsvf8HgwMJtbBA3', | ||
'amount': 47805070468192, | ||
'message': 'second message' | ||
}, | ||
], | ||
'outputOrder': [0, 1, 2] | ||
}; | ||
|
||
return txp; | ||
}; | ||
|
||
const signedTxp = { | ||
'actions': [ | ||
{ | ||
'version': '1.0.0', | ||
'createdOn': 1621538686, | ||
'copayerId': '5a49148ea402f06943b511912f31bc9114153e6055c38642fe789f7b2c7bf9f8', | ||
'type': 'accept', | ||
'signatures': [ | ||
'3045022100a9bee101f13eeb8f6bdf1b6421974a17b2aeb0bcf080526df20e93483a67bbca022071ba69e707430136fb65488b1e5413eb54279770b74b7e15fe15aeac16770ceb' | ||
], | ||
'xpub': 'tpubDDtorxcvdjDwsYDCkSUTigtBGh1N5EjrDCqWwkCEz69cBHCh2mZoHxdfQzaZBd7tN5vsUxSchDxxGYxEQrbkyeUr4iWQJ89tTKgZpgivS8P', | ||
'comment': null, | ||
'copayerName': 'copayer 1' | ||
} | ||
], | ||
'version': 3, | ||
'createdOn': 1621538640, | ||
'id': 'B8Frw4L4mTZumUx5D1heVg', | ||
'walletId': 'd98853c7-5a4b-48de-9f6c-8fb36aa271f1', | ||
'creatorId': '5a49148ea402f06943b511912f31bc9114153e6055c38642fe789f7b2c7bf9f8', | ||
'coin': 'doge', | ||
'network': 'testnet', | ||
'outputs': [ | ||
{ | ||
'amount': 5743168500, | ||
'toAddress': 'mwYE4TAQQF4F8aRZCVG8YXQDpuFRfjh3Mg', | ||
'message': null | ||
} | ||
], | ||
'amount': 5743168500, | ||
'message': 'some message', | ||
'payProUrl': null, | ||
'changeAddress': { | ||
'version': '1.0.0', | ||
'createdOn': 1621538640, | ||
'address': 'mwSgYPXVExR1BCL72SCmh2nSDrsGX2bssj', | ||
'walletId': 'd98853c7-5a4b-48de-9f6c-8fb36aa271f1', | ||
'isChange': true, | ||
'path': 'm/1/0', | ||
'publicKeys': [ | ||
'0392e5436961b4301a54fedab9b28ff70e9d90620304d93b07a1631be0d5e75084' | ||
], | ||
'coin': 'doge', | ||
'network': 'testnet', | ||
'type': 'P2PKH', | ||
'hasActivity': null, | ||
'beRegistered': null | ||
}, | ||
'inputs': [ | ||
{ | ||
'address': 'n1Y8s9bFx693pnf8A5v2YR5QbbR4N6e89Q', | ||
'satoshis': 10000000000000, | ||
'amount': 100000, | ||
'scriptPubKey': '76a914db9bc16a822e747bdf681bb732bda92fd8fac4bf88ac', | ||
'txid': '5354f8793ee3a6b4626fe171d712d864bde91073535286a35c3ddd3a77d4a1b8', | ||
'vout': 0, | ||
'locked': false, | ||
'confirmations': 11, | ||
'path': 'm/0/8', | ||
'publicKeys': [ | ||
'02f4526941f57f37b8f1cd4970091ebcd1701980a82d26a781b2e44b384609eb22' | ||
] | ||
} | ||
], | ||
'walletM': 1, | ||
'walletN': 1, | ||
'requiredSignatures': 1, | ||
'requiredRejections': 1, | ||
'status': 'broadcasted', | ||
'txid': '5b0e1d4eaa939bb219e7f054c24dda8e1a0bca392c108ed3017f84c82f13ae97', | ||
'broadcastedOn': 1621538687, | ||
'inputPaths': [ | ||
'm/0/8' | ||
], | ||
'outputOrder': [ | ||
1, | ||
0 | ||
], | ||
'fee': 22500000, | ||
'feeLevel': 'normal', | ||
'feePerKb': 100000000, | ||
'excludeUnconfirmedUtxos': true, | ||
'addressType': 'P2PKH', | ||
'customData': null, | ||
'proposalSignature': '3044022025f2b5b1da1c45c4103a21448be4e1095acd908629acc89dc3398fa0d4621a2302206b809ffff1a896c367a9ba35fb2c100f187ab73c4ee590ba4aff778a91ee9ee3', | ||
'signingMethod': 'ecdsa', | ||
'proposalSignaturePubKey': null, | ||
'proposalSignaturePubKeySig': null, | ||
'lockUntilBlockHeight': null, | ||
'gasPrice': null, | ||
'from': null, | ||
'nonce': null, | ||
'gasLimit': null, | ||
'data': null, | ||
'tokenAddress': null, | ||
'multisigContractAddress': null, | ||
'multisigTxId': null, | ||
'destinationTag': null, | ||
'invoiceID': null, | ||
'derivationStrategy': 'BIP44', | ||
'creatorName': 'copayer 1', | ||
'raw': '0100000001b8a1d4773add3d5ca38652537310e9bd64d812d771e16f62b4a6e33e79f85453000000006b483045022100a9bee101f13eeb8f6bdf1b6421974a17b2aeb0bcf080526df20e93483a67bbca022071ba69e707430136fb65488b1e5413eb54279770b74b7e15fe15aeac16770ceb012102f4526941f57f37b8f1cd4970091ebcd1701980a82d26a781b2e44b384609eb22ffffffff026c81c9f6160900001976a914aeb332ea003a7efb5dab0dcc56d19fed84e26afb88acf4cb5156010000001976a914afbf96bfb28815cad8205c8f2f5a86819136664c88ac00000000', | ||
'note': null, | ||
'isPending': false | ||
}; |
Oops, something went wrong.