|
|
|
@ -54,6 +54,7 @@ var cnUtil = function(currencyConfig)
|
|
|
|
|
var ENCRYPTED_PAYMENT_ID_TAIL = 141;
|
|
|
|
|
var CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = config.addressPrefix;
|
|
|
|
|
var CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = config.integratedAddressPrefix;
|
|
|
|
|
var CRYPTONOTE_PUBLIC_INTEGRATED_SUBADDRESS_BASE58_PREFIX = 42;
|
|
|
|
|
var UINT64_MAX = new JSBigInt(2).pow(64);
|
|
|
|
|
var CURRENT_TX_VERSION = 2;
|
|
|
|
|
var OLD_TX_VERSION = 1;
|
|
|
|
@ -489,8 +490,9 @@ var cnUtil = function(currencyConfig)
|
|
|
|
|
var dec = cnBase58.decode(address);
|
|
|
|
|
var expectedPrefix = this.encode_varint(CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX);
|
|
|
|
|
var expectedPrefixInt = this.encode_varint(CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX);
|
|
|
|
|
var expectedPrefixSub = this.encode_varint(CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX);
|
|
|
|
|
var prefix = dec.slice(0, expectedPrefix.length);
|
|
|
|
|
if (prefix !== expectedPrefix && prefix !== expectedPrefixInt) {
|
|
|
|
|
if (prefix !== expectedPrefix && prefix !== expectedPrefixInt && prefix !== expectedPrefixSub) {
|
|
|
|
|
throw "Invalid address prefix";
|
|
|
|
|
}
|
|
|
|
|
dec = dec.slice(expectedPrefix.length);
|
|
|
|
@ -520,6 +522,14 @@ var cnUtil = function(currencyConfig)
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.is_subaddress = function(addr) {
|
|
|
|
|
var decoded = cnBase58.decode(addr);
|
|
|
|
|
var subaddressPrefix = this.encode_varint(CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX);
|
|
|
|
|
var prefix = decoded.slice(0, subaddressPrefix.length);
|
|
|
|
|
|
|
|
|
|
return (prefix === subaddressPrefix);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.valid_keys = function(view_pub, view_sec, spend_pub, spend_sec) {
|
|
|
|
|
var expected_view_pub = this.sec_key_to_pub(view_sec);
|
|
|
|
@ -1623,7 +1633,6 @@ var cnUtil = function(currencyConfig)
|
|
|
|
|
} else {
|
|
|
|
|
tx.signatures = [];
|
|
|
|
|
}
|
|
|
|
|
tx.extra = this.add_pub_key_to_extra(tx.extra, txkey.pub);
|
|
|
|
|
|
|
|
|
|
var in_contexts = [];
|
|
|
|
|
var inputs_money = JSBigInt.ZERO;
|
|
|
|
@ -1670,7 +1679,23 @@ var cnUtil = function(currencyConfig)
|
|
|
|
|
throw "dst.amount < 0"; //amount can be zero if no change
|
|
|
|
|
}
|
|
|
|
|
dsts[i].keys = this.decode_address(dsts[i].address);
|
|
|
|
|
var out_derivation = this.generate_key_derivation(dsts[i].keys.view, txkey.sec);
|
|
|
|
|
|
|
|
|
|
// R = rD for subaddresses
|
|
|
|
|
if(this.is_subaddress(dsts[i].address)) {
|
|
|
|
|
txkey.pub = ge_scalarmult(dsts[i].keys.spend, txkey.sec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var out_derivation;
|
|
|
|
|
|
|
|
|
|
// send change to ourselves
|
|
|
|
|
if(dsts[i].keys.view == keys.view.pub) {
|
|
|
|
|
out_derivation = this.generate_key_derivation(txkey.pub, keys.view.sec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
out_derivation = this.generate_key_derivation(dsts[i].keys.view, txkey.sec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rct) {
|
|
|
|
|
amountKeys.push(this.derivation_to_scalar(out_derivation, out_index));
|
|
|
|
|
}
|
|
|
|
@ -1687,6 +1712,10 @@ var cnUtil = function(currencyConfig)
|
|
|
|
|
++out_index;
|
|
|
|
|
outputs_money = outputs_money.add(dsts[i].amount);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// add pub key to extra after we know whether to use R = rG or R = rD
|
|
|
|
|
tx.extra = this.add_pub_key_to_extra(tx.extra, txkey.pub);
|
|
|
|
|
|
|
|
|
|
if (outputs_money.add(fee_amount).compare(inputs_money) > 0) {
|
|
|
|
|
throw "outputs money (" + this.formatMoneyFull(outputs_money) + ") + fee (" + this.formatMoneyFull(fee_amount) + ") > inputs money (" + this.formatMoneyFull(inputs_money) + ")";
|
|
|
|
|
}
|
|
|
|
@ -2067,4 +2096,4 @@ var cnUtil = function(currencyConfig)
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
exports.cnUtil = cnUtil
|
|
|
|
|
exports.cnUtil = cnUtil
|
|
|
|
|