covenants: refactor a number of things.
This commit is contained in:
parent
0d08a19353
commit
2ffbbded2e
4 changed files with 284 additions and 146 deletions
|
|
@ -211,7 +211,6 @@ class NameDB {
|
|||
|
||||
const {prevout} = input;
|
||||
const coin = view.getOutput(prevout);
|
||||
assert(coin);
|
||||
const uc = coin.covenant;
|
||||
|
||||
const index = input.link;
|
||||
|
|
@ -219,10 +218,12 @@ class NameDB {
|
|||
const {covenant} = output;
|
||||
|
||||
if (uc.type === types.BID) {
|
||||
assert(covenant.type === types.REVEAL);
|
||||
|
||||
const auction = await view.getAuctionFor(this, prevout);
|
||||
assert(auction);
|
||||
|
||||
if (auction.state(height, network) !== states.REVEAL)
|
||||
if (auction.state(height, network) > states.REVEAL)
|
||||
return false;
|
||||
|
||||
auction.removeBid(prevout.hash, prevout.index);
|
||||
|
|
@ -233,6 +234,10 @@ class NameDB {
|
|||
}
|
||||
|
||||
if (uc.type === types.REVEAL) {
|
||||
assert(covenant.type === types.REDEEM
|
||||
|| covenant.type === types.UPDATE
|
||||
|| covenant.type === types.RELEASE);
|
||||
|
||||
const auction = await view.getAuctionFor(this, prevout);
|
||||
assert(auction);
|
||||
|
||||
|
|
@ -244,7 +249,7 @@ class NameDB {
|
|||
if (owner.isNull())
|
||||
owner = await this.pickWinner(auction.nameHash);
|
||||
|
||||
if (covenant.type !== types.UPDATE) {
|
||||
if (covenant.type === types.REDEEM) {
|
||||
// Must be the loser in order
|
||||
// to redeem the money now.
|
||||
if (prevout.equals(owner))
|
||||
|
|
@ -253,23 +258,29 @@ class NameDB {
|
|||
continue;
|
||||
}
|
||||
|
||||
assert(covenant.type === types.UPDATE);
|
||||
|
||||
// Must be the winner in order
|
||||
// to update the name record.
|
||||
if (!prevout.equals(owner))
|
||||
return false;
|
||||
|
||||
auction.removeReveal(prevout.hash, prevout.index);
|
||||
auction.setOwner(hash, index);
|
||||
auction.setData(covenant.items[1]);
|
||||
auction.save();
|
||||
auction.queue();
|
||||
|
||||
if (covenant.type === types.UPDATE) {
|
||||
auction.setOwner(hash, index);
|
||||
auction.setData(covenant.items[1]);
|
||||
auction.save();
|
||||
auction.queue();
|
||||
} else {
|
||||
auction.remove();
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uc.type === types.UPDATE) {
|
||||
assert(covenant.type === types.UPDATE
|
||||
|| covenant.type === types.RELEASE);
|
||||
|
||||
const auction = await view.getAuctionFor(this, prevout);
|
||||
assert(auction);
|
||||
|
||||
|
|
@ -280,10 +291,15 @@ class NameDB {
|
|||
if (!prevout.equals(auction.owner))
|
||||
return false;
|
||||
|
||||
auction.setOwner(hash, index);
|
||||
auction.setData(covenant.items[1]);
|
||||
auction.save();
|
||||
auction.queue();
|
||||
if (covenant.type === types.UPDATE) {
|
||||
auction.setOwner(hash, index);
|
||||
auction.setData(covenant.items[1]);
|
||||
auction.save();
|
||||
auction.queue();
|
||||
} else {
|
||||
auction.remove();
|
||||
auction.unqueue();
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
|
@ -299,6 +315,9 @@ class NameDB {
|
|||
const auction =
|
||||
await view.ensureAuction(this, name, nameHash, height);
|
||||
|
||||
if (!auction.owner.isNull())
|
||||
return false;
|
||||
|
||||
if (auction.state(height, network) !== states.BIDDING)
|
||||
return false;
|
||||
|
||||
|
|
@ -365,9 +384,11 @@ class NameDB {
|
|||
const {covenant} = output;
|
||||
|
||||
if (uc.type === types.BID) {
|
||||
assert(covenant.type === types.REVEAL);
|
||||
|
||||
const auction = await view.getAuctionFor(this, prevout);
|
||||
assert(auction);
|
||||
assert(auction.state(height, network) === states.REVEAL);
|
||||
assert(auction.state(height, network) <= states.REVEAL);
|
||||
|
||||
auction.removeReveal(hash, index);
|
||||
auction.save();
|
||||
|
|
@ -376,18 +397,26 @@ class NameDB {
|
|||
}
|
||||
|
||||
if (uc.type === types.REVEAL) {
|
||||
assert(covenant.type === types.REDEEM
|
||||
|| covenant.type === types.UPDATE
|
||||
|| covenant.type === types.RELEASE);
|
||||
|
||||
// XXX Figure out what to do here:
|
||||
// Add a `released` property to auction object!
|
||||
assert(covenant.type !== types.RELEASE);
|
||||
|
||||
const auction = await view.getAuctionFor(this, prevout);
|
||||
assert(auction);
|
||||
assert(auction.state(height, network) === states.CLOSED);
|
||||
|
||||
if (covenant.type !== types.UPDATE) {
|
||||
if (covenant.type === types.REDEEM) {
|
||||
assert(!prevout.equals(auction.owner));
|
||||
auction.addReveal(prevout.hash, prevout.index, coin.value);
|
||||
auction.save();
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(!prevout.equals(auction.owner));
|
||||
assert(prevout.equals(auction.owner));
|
||||
|
||||
// Switch back to previous owner and data.
|
||||
auction.addReveal(prevout.hash, prevout.index, coin.value);
|
||||
|
|
@ -400,7 +429,12 @@ class NameDB {
|
|||
}
|
||||
|
||||
if (uc.type === types.UPDATE) {
|
||||
assert(covenant.type === types.UPDATE);
|
||||
assert(covenant.type === types.UPDATE
|
||||
|| covenant.type === types.RELEASE);
|
||||
|
||||
// XXX Figure out what to do here:
|
||||
// Add a `released` property to auction object!
|
||||
assert(covenant.type !== types.RELEASE);
|
||||
|
||||
const auction = await view.getAuctionFor(this, prevout);
|
||||
assert(auction);
|
||||
|
|
|
|||
|
|
@ -4,13 +4,17 @@ const assert = require('assert');
|
|||
const bio = require('bufio');
|
||||
const blake2b = require('bcrypto/lib/blake2b');
|
||||
|
||||
// TODO:
|
||||
// locktime for transfer
|
||||
// no duplicate names
|
||||
// early reveals
|
||||
|
||||
const types = {
|
||||
NONE: 0,
|
||||
BID: 1,
|
||||
REVEAL: 2,
|
||||
UPDATE: 3,
|
||||
REDEEM: 4,
|
||||
// locktime for transfer
|
||||
RELEASE: 5
|
||||
};
|
||||
|
||||
|
|
@ -19,7 +23,7 @@ exports.types = types;
|
|||
exports.MAX_NAME_SIZE = 255;
|
||||
exports.MAX_RECORD_SIZE = 512;
|
||||
exports.MAX_COVENANT_SIZE = 1 + exports.MAX_RECORD_SIZE;
|
||||
exports.MAX_COVENANT_TYPE = types.UPDATE;
|
||||
exports.MAX_COVENANT_TYPE = types.RELEASE;
|
||||
|
||||
exports.BIDDING_PERIOD = 1;
|
||||
exports.REVEAL_PERIOD = 1;
|
||||
|
|
@ -123,6 +127,9 @@ exports.hasSaneCovenants = function hasSaneCovenants(tx) {
|
|||
for (const {covenant} of tx.outputs) {
|
||||
if (covenant.type !== types.NONE)
|
||||
return false;
|
||||
|
||||
if (covenant.items.length !== 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -148,14 +155,19 @@ exports.hasSaneCovenants = function hasSaneCovenants(tx) {
|
|||
const {covenant} = tx.outputs[i];
|
||||
|
||||
switch (covenant.type) {
|
||||
case types.NONE:
|
||||
case types.NONE: {
|
||||
// No inputs can be linked.
|
||||
if (links.has(i))
|
||||
return false;
|
||||
|
||||
// Just a regular payment.
|
||||
// Can come from a payment or a reveal (loser).
|
||||
if (covenant.items.length !== 0)
|
||||
return false;
|
||||
|
||||
break;
|
||||
case types.BID:
|
||||
}
|
||||
case types.BID: {
|
||||
// No inputs can be linked.
|
||||
if (links.has(i))
|
||||
return false;
|
||||
|
|
@ -173,7 +185,8 @@ exports.hasSaneCovenants = function hasSaneCovenants(tx) {
|
|||
return false;
|
||||
|
||||
break;
|
||||
case types.REVEAL:
|
||||
}
|
||||
case types.REVEAL: {
|
||||
// Has to come from a BID.
|
||||
if (!links.has(i))
|
||||
return false;
|
||||
|
|
@ -191,7 +204,8 @@ exports.hasSaneCovenants = function hasSaneCovenants(tx) {
|
|||
return false;
|
||||
|
||||
break;
|
||||
case types.UPDATE:
|
||||
}
|
||||
case types.UPDATE: {
|
||||
// Has to come from an UPDATE or REVEAL.
|
||||
if (!links.has(i))
|
||||
return false;
|
||||
|
|
@ -209,7 +223,8 @@ exports.hasSaneCovenants = function hasSaneCovenants(tx) {
|
|||
return false;
|
||||
|
||||
break;
|
||||
case types.REDEEM:
|
||||
}
|
||||
case types.REDEEM: {
|
||||
// Has to come from a REVEAL.
|
||||
if (!links.has(i))
|
||||
return false;
|
||||
|
|
@ -223,7 +238,8 @@ exports.hasSaneCovenants = function hasSaneCovenants(tx) {
|
|||
return false;
|
||||
|
||||
break;
|
||||
case types.RELEASE:
|
||||
}
|
||||
case types.RELEASE: {
|
||||
// Has to come from an UPDATE or REVEAL.
|
||||
if (!links.has(i))
|
||||
return false;
|
||||
|
|
@ -237,10 +253,12 @@ exports.hasSaneCovenants = function hasSaneCovenants(tx) {
|
|||
return false;
|
||||
|
||||
break;
|
||||
default:
|
||||
}
|
||||
default: {
|
||||
// Unknown covenant.
|
||||
// Don't enforce anything.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -259,27 +277,27 @@ exports.verifyCovenants = function verifyCovenants(tx, view) {
|
|||
|
||||
const uc = coin.covenant;
|
||||
|
||||
// XXX More verification here?
|
||||
if (input.link === 0xffffffff)
|
||||
continue;
|
||||
|
||||
assert(input.link < tx.outputs.length);
|
||||
|
||||
// Output the covenant is linked to.
|
||||
const output = tx.outputs[input.link];
|
||||
const {covenant} = output;
|
||||
if (input.link !== 0xffffffff)
|
||||
assert(input.link < tx.outputs.length);
|
||||
|
||||
switch (uc.type) {
|
||||
case types.NONE: {
|
||||
// Payment has to go to either
|
||||
// another payment, or a bid.
|
||||
if (covenant.type !== types.NONE
|
||||
&& covenant.type !== types.BID) {
|
||||
case types.NONE:
|
||||
case types.REDEEM: {
|
||||
// Cannot be linked.
|
||||
if (input.link !== 0xffffffff)
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case types.BID: {
|
||||
// Must be be linked.
|
||||
if (input.link === 0xffffffff)
|
||||
return false;
|
||||
|
||||
// Output the covenant is linked to.
|
||||
const output = tx.outputs[input.link];
|
||||
const {covenant} = output;
|
||||
|
||||
// Bid has to go to a reveal.
|
||||
if (covenant.type !== types.REVEAL)
|
||||
return false;
|
||||
|
|
@ -304,58 +322,76 @@ exports.verifyCovenants = function verifyCovenants(tx, view) {
|
|||
break;
|
||||
}
|
||||
case types.REVEAL: {
|
||||
// Must be be linked.
|
||||
if (input.link === 0xffffffff)
|
||||
return false;
|
||||
|
||||
// Output the covenant is linked to.
|
||||
const output = tx.outputs[input.link];
|
||||
const {covenant} = output;
|
||||
|
||||
// Reveal has to go to an update, or
|
||||
// a redeem (in the case of the loser).
|
||||
if (covenant.type !== types.UPDATE
|
||||
&& covenant.type !== types.REDEEM) {
|
||||
return false;
|
||||
}
|
||||
switch (covenant.type) {
|
||||
case types.UPDATE:
|
||||
case types.RELEASE: {
|
||||
// Names must match.
|
||||
if (!covenant.items[0].equals(uc.items[0]))
|
||||
return false;
|
||||
|
||||
// Money is now locked up forever.
|
||||
if (covenant.type === types.UPDATE) {
|
||||
// Names must match.
|
||||
if (!covenant.items[0].equals(uc.items[0]))
|
||||
return false;
|
||||
// Money is now locked up forever.
|
||||
if (output.value !== coin.value)
|
||||
return false;
|
||||
|
||||
if (output.value !== coin.value)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case types.REDEEM: {
|
||||
// Names must match.
|
||||
if (!covenant.items[0].equals(uc.items[0]))
|
||||
return false;
|
||||
|
||||
if (covenant.type === types.REDEEM) {
|
||||
// Names must match.
|
||||
if (!covenant.items[0].equals(uc.items[0]))
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case types.UPDATE: {
|
||||
// Names must match.
|
||||
if (!covenant.items[0].equals(uc.items[0]))
|
||||
// Must be be linked.
|
||||
if (input.link === 0xffffffff)
|
||||
return false;
|
||||
|
||||
// Money is now locked up forever.
|
||||
if (output.value !== coin.value)
|
||||
return false;
|
||||
// Output the covenant is linked to.
|
||||
const output = tx.outputs[input.link];
|
||||
const {covenant} = output;
|
||||
|
||||
if (covenant.type !== types.UPDATE)
|
||||
return false;
|
||||
// Can only send to another update or release.
|
||||
switch (covenant.type) {
|
||||
case types.UPDATE:
|
||||
case types.RELEASE: {
|
||||
// Names must match.
|
||||
if (!covenant.items[0].equals(uc.items[0]))
|
||||
return false;
|
||||
|
||||
break;
|
||||
}
|
||||
case types.REDEEM: {
|
||||
// Can go anywhere.
|
||||
if (covenant.items.length !== 0)
|
||||
return false;
|
||||
// Money is now locked up forever.
|
||||
if (output.value !== coin.value)
|
||||
return false;
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case types.RELEASE: {
|
||||
// Can go anywhere.
|
||||
if (covenant.items.length !== 0)
|
||||
return false;
|
||||
|
||||
break;
|
||||
// Releases are perma-burned.
|
||||
return false;
|
||||
}
|
||||
default: {
|
||||
// Unknown covenant.
|
||||
|
|
|
|||
|
|
@ -1125,38 +1125,8 @@ class MTX extends TX {
|
|||
for (const coin of select.chosen)
|
||||
this.addCoin(coin);
|
||||
|
||||
// XXX
|
||||
const map = new Map();
|
||||
|
||||
for (let i = 0; i < this.outputs.length; i++) {
|
||||
const {covenant} = this.outputs[i];
|
||||
|
||||
if (covenant.items.length < 1)
|
||||
continue;
|
||||
|
||||
const name = covenant.string(0);
|
||||
map.set(name, i);
|
||||
}
|
||||
|
||||
for (let i = 0; i < select.chosen.length; i++) {
|
||||
if (map.size === 0)
|
||||
break;
|
||||
|
||||
const {covenant} = select.chosen[i];
|
||||
|
||||
if (covenant.items.length < 1)
|
||||
continue;
|
||||
|
||||
const name = covenant.string(0);
|
||||
const link = map.get(name);
|
||||
|
||||
if (link == null)
|
||||
continue;
|
||||
|
||||
map.delete(name);
|
||||
|
||||
this.inputs[i].link = link;
|
||||
}
|
||||
if (select.prevout)
|
||||
this.inputs[0].link = select.link;
|
||||
|
||||
// Attempt to subtract fee.
|
||||
if (select.subtractFee) {
|
||||
|
|
@ -1411,8 +1381,8 @@ class CoinSelector {
|
|||
this.maxFee = -1;
|
||||
this.round = false;
|
||||
this.changeAddress = null;
|
||||
// XXX
|
||||
this.map = new Map();
|
||||
this.prevout = null;
|
||||
this.link = -1;
|
||||
|
||||
// Needed for size estimation.
|
||||
this.estimate = null;
|
||||
|
|
@ -1508,6 +1478,12 @@ class CoinSelector {
|
|||
this.estimate = options.estimate;
|
||||
}
|
||||
|
||||
if (options.covenant) {
|
||||
assert(typeof options.covenant === 'object');
|
||||
this.prevout = options.covenant.prevout;
|
||||
this.link = options.covenant.link;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -1524,17 +1500,6 @@ class CoinSelector {
|
|||
this.change = 0;
|
||||
this.fee = CoinSelector.MIN_FEE;
|
||||
this.tx.inputs.length = 0;
|
||||
this.map.clear();
|
||||
|
||||
// XXX
|
||||
for (let i = 0; i < this.tx.outputs.length; i++) {
|
||||
const {covenant} = this.tx.outputs[i];
|
||||
|
||||
if (covenant.items.length < 1)
|
||||
continue;
|
||||
|
||||
this.map.set(covenant.string(0), i);
|
||||
}
|
||||
|
||||
switch (this.selection) {
|
||||
case 'all':
|
||||
|
|
@ -1624,6 +1589,22 @@ class CoinSelector {
|
|||
return Math.min(fee, CoinSelector.MAX_FEE);
|
||||
}
|
||||
|
||||
findCoin(prevout) {
|
||||
for (let i = 0; i < this.coins.length; i++) {
|
||||
const {hash, index} = this.coins[i];
|
||||
|
||||
if (index !== prevout.index)
|
||||
continue;
|
||||
|
||||
if (hash !== prevout.hash)
|
||||
continue;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fund the transaction with more
|
||||
* coins if the `output value + fee`
|
||||
|
|
@ -1631,26 +1612,11 @@ class CoinSelector {
|
|||
*/
|
||||
|
||||
fund() {
|
||||
// XXX
|
||||
for (let i = 0; i < this.coins.length; i++) {
|
||||
if (this.map.size === 0)
|
||||
break;
|
||||
|
||||
const coin = this.coins[i];
|
||||
const {covenant} = coin;
|
||||
|
||||
if (covenant.items.length < 1)
|
||||
continue;
|
||||
|
||||
const name = covenant.string(0);
|
||||
|
||||
if (!this.map.has(name))
|
||||
continue;
|
||||
|
||||
this.map.delete(name);
|
||||
this.coins.splice(i, 1);
|
||||
i -= 1;
|
||||
|
||||
if (this.prevout && this.chosen.length === 0) {
|
||||
const index = this.findCoin(this.prevout);
|
||||
assert(index !== -1, 'Coin not found.');
|
||||
const coin = this.coins[index];
|
||||
this.coins.splice(index, 1);
|
||||
this.tx.addCoin(coin);
|
||||
this.chosen.push(coin);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -340,6 +340,29 @@ class MemWallet {
|
|||
|
||||
this.auctions.set(name, [new Outpoint(hash, i), 3]);
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
if (!path)
|
||||
break;
|
||||
|
||||
const name = covenant.string(0);
|
||||
|
||||
// We lost.
|
||||
this.auctions.delete(name);
|
||||
this.bids.delete(name);
|
||||
this.values.delete(name);
|
||||
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
const name = covenant.string(0);
|
||||
|
||||
// Someone released it.
|
||||
this.auctions.delete(name);
|
||||
this.bids.delete(name);
|
||||
this.values.delete(name);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -388,6 +411,75 @@ class MemWallet {
|
|||
const op = input.prevout.toKey();
|
||||
const coin = this.getUndo(op);
|
||||
|
||||
switch (covenant.type) {
|
||||
case 1: {
|
||||
if (!coin)
|
||||
break;
|
||||
|
||||
const name = covenant.string(0);
|
||||
|
||||
this.auctions.delete(name);
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
const name = covenant.string(0);
|
||||
const nonce = covenant.items[1];
|
||||
|
||||
if (!this.auctions.has(name))
|
||||
break;
|
||||
|
||||
if (!this.bids.has(name))
|
||||
break;
|
||||
|
||||
const key = Outpoint.toKey(hash, i);
|
||||
|
||||
const bids = this.bids.get(name);
|
||||
|
||||
bids.delete(key);
|
||||
|
||||
if (bids.size === 0)
|
||||
this.bids.delete(name);
|
||||
|
||||
if (!coin)
|
||||
break;
|
||||
|
||||
this.values.delete(name);
|
||||
this.auctions.set(name, [new Outpoint(hash, i), 1]);
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
if (!coin)
|
||||
break;
|
||||
|
||||
const name = covenant.string(0);
|
||||
|
||||
this.auctions.set(name, [new Outpoint(hash, i), 2]);
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
if (!coin)
|
||||
break;
|
||||
|
||||
const name = covenant.string(0);
|
||||
|
||||
// We lost.
|
||||
this.auctions.set(name, [new Outpoint(hash, i), 2]);
|
||||
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
const name = covenant.string(0);
|
||||
|
||||
// Someone released it.
|
||||
this.auctions.set(name, [new Outpoint(hash, i), 3]);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!coin)
|
||||
continue;
|
||||
|
||||
|
|
@ -479,7 +571,10 @@ class MemWallet {
|
|||
const mtx = new MTX();
|
||||
mtx.outputs.push(output);
|
||||
|
||||
return this._create(mtx, options, prevout);
|
||||
return this._create(mtx, options, {
|
||||
prevout,
|
||||
link: 0
|
||||
});
|
||||
}
|
||||
|
||||
async registerName(name, data, options) {
|
||||
|
|
@ -511,7 +606,10 @@ class MemWallet {
|
|||
const mtx = new MTX();
|
||||
mtx.outputs.push(output);
|
||||
|
||||
return this._create(mtx, options, prevout);
|
||||
return this._create(mtx, options, {
|
||||
prevout,
|
||||
link: 0
|
||||
});
|
||||
}
|
||||
|
||||
async redeemName(name, options) {
|
||||
|
|
@ -531,7 +629,10 @@ class MemWallet {
|
|||
const mtx = new MTX();
|
||||
mtx.outputs.push(output);
|
||||
|
||||
return this._create(mtx, options);
|
||||
return this._create(mtx, options, {
|
||||
prevout,
|
||||
link: 0
|
||||
});
|
||||
}
|
||||
|
||||
isWinner(name) {
|
||||
|
|
@ -556,7 +657,7 @@ class MemWallet {
|
|||
return this.coins.has(winner);
|
||||
}
|
||||
|
||||
fund(mtx, options) {
|
||||
fund(mtx, options, covenant) {
|
||||
const coins = this.getCoins();
|
||||
|
||||
if (!options)
|
||||
|
|
@ -571,7 +672,8 @@ class MemWallet {
|
|||
changeAddress: this.getChange(),
|
||||
height: -1,
|
||||
rate: options.rate,
|
||||
maxFee: options.maxFee
|
||||
maxFee: options.maxFee,
|
||||
covenant
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -586,8 +688,8 @@ class MemWallet {
|
|||
mtx.sign(keys);
|
||||
}
|
||||
|
||||
async _create(mtx, options) {
|
||||
await this.fund(mtx, options);
|
||||
async _create(mtx, options, covenant) {
|
||||
await this.fund(mtx, options, covenant);
|
||||
|
||||
assert(mtx.getFee() <= MTX.Selector.MAX_FEE, 'TX exceeds MAX_FEE.');
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue