Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DigiByte #1993

Merged
merged 9 commits into from Apr 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions client/asset/btc/btc.go
Expand Up @@ -368,12 +368,12 @@ type BTCCloneCFG struct {
// getrawtransaction RPC.
NumericGetRawRPC bool
// LegacyValidateAddressRPC uses the validateaddress endpoint instead of
// getwalletinfo in order to discover ownership of an address.
// getaddressinfo in order to discover ownership of an address.
LegacyValidateAddressRPC bool
// SingularWallet signals that the node software supports only one wallet,
// so the RPC endpoint does not have a /wallet/{walletname} path.
SingularWallet bool
// UnlockSpends manually unlocks outputs as they are spent. Most asses will
// UnlockSpends manually unlocks outputs as they are spent. Most assets will
// unlock wallet outputs automatically as they are spent.
UnlockSpends bool
// ConstantDustLimit is used if an asset enforces a dust limit (minimum
Expand Down Expand Up @@ -2836,7 +2836,7 @@ func (btc *baseWallet) sizeAndFeesOfUnconfirmedTxs(txs []*GetTransactionResult)
}

fees += fee
size += dexbtc.MsgTxVBytes(msgTx)
size += btc.calcTxSize(msgTx)
}

return size, fees, nil
Expand Down Expand Up @@ -4751,7 +4751,7 @@ func (btc *baseWallet) signTxAndAddChange(baseTx *wire.MsgTx, addr btcutil.Addre
// Add the change output.
vSize0 := btc.calcTxSize(baseTx)
baseTx.AddTxOut(changeOutput)
changeSize := dexbtc.MsgTxVBytes(baseTx) - vSize0 // may be dexbtc.P2WPKHOutputSize
changeSize := btc.calcTxSize(baseTx) - vSize0 // may be dexbtc.P2WPKHOutputSize
chappjc marked this conversation as resolved.
Show resolved Hide resolved
addrStr, _ := btc.stringAddr(addr, btc.chainParams) // just for logging
btc.log.Debugf("Change output size = %d, addr = %s", changeSize, addrStr)

Expand Down
152 changes: 152 additions & 0 deletions client/asset/dgb/dgb.go
@@ -0,0 +1,152 @@
// This code is available on the terms of the project LICENSE.md file,
// also available online at https://blueoakcouncil.org/license/1.0.0.

package dgb

import (
"fmt"

"decred.org/dcrdex/client/asset"
"decred.org/dcrdex/client/asset/btc"
"decred.org/dcrdex/dex"
dexbtc "decred.org/dcrdex/dex/networks/btc"
dexdgb "decred.org/dcrdex/dex/networks/dgb"

"github.com/btcsuite/btcd/chaincfg"
)

const (
version = 0
BipID = 20

// dustLimit = 1_000_000 // sats => 0.01 DGB, the "soft" limit (DEFAULT_DUST_LIMIT) **TODO check for dgb**

minNetworkVersion = 7170300
walletTypeRPC = "digibytedRPC"
defaultRedeemConfTarget = 2
)

var (
configOpts = append(btc.RPCConfigOpts("DigiByte", "14022"), []*asset.ConfigOption{
{
Key: "fallbackfee",
DisplayName: "Fallback fee rate",
Description: "DigiByte's 'fallbackfee' rate. Units: DGB/kB",
DefaultValue: dexdgb.DefaultFee * 1000 / 1e8, // higher than BTC default
},
{
Key: "feeratelimit",
DisplayName: "Highest acceptable fee rate",
Description: "This is the highest network fee rate you are willing to " +
"pay on swap transactions. If feeratelimit is lower than a market's " +
"maxfeerate, you will not be able to trade on that market with this " +
"wallet. Units: BTC/kB",
DefaultValue: dexdgb.DefaultFeeRateLimit * 1000 / 1e8, // higher than BTC default
},
{
Key: "redeemconftarget",
DisplayName: "Redeem confirmation target",
Description: "The target number of blocks for the redeem transaction " +
"to be mined. Used to set the transaction's fee rate. " +
"(default: 2 blocks)",
DefaultValue: defaultRedeemConfTarget,
},
{
Key: "txsplit",
DisplayName: "Pre-split funding inputs",
Description: "When placing an order, create a \"split\" transaction to fund the order without locking more of the wallet balance than " +
"necessary. Otherwise, excess funds may be reserved to fund the order until the first swap contract is broadcast " +
"during match settlement, or the order is canceled. This an extra transaction for which network mining fees are paid. " +
"Used only for standing-type orders, e.g. limit orders without immediate time-in-force.",
IsBoolean: true,
DefaultValue: true, // low fee, fast chain
}, // no ExternalFeeEstimator, so no apifeefallback option
chappjc marked this conversation as resolved.
Show resolved Hide resolved
}...)
// WalletInfo defines some general information about a DigiByte wallet.
WalletInfo = &asset.WalletInfo{
Name: "DigiByte",
Version: version,
SupportedVersions: []uint32{version},
UnitInfo: dexdgb.UnitInfo,
AvailableWallets: []*asset.WalletDefinition{{
Type: walletTypeRPC,
Tab: "External",
Description: "Connect to digibyted",
DefaultConfigPath: dexbtc.SystemConfigPath("digibyte"),
ConfigOpts: configOpts,
}},
}
)

func init() {
asset.Register(BipID, &Driver{})
}

// Driver implements asset.Driver.
type Driver struct{}

// Open creates the DGB exchange wallet. Start the wallet with its Run method.
func (d *Driver) Open(cfg *asset.WalletConfig, logger dex.Logger, network dex.Network) (asset.Wallet, error) {
return NewWallet(cfg, logger, network)
}

// DecodeCoinID creates a human-readable representation of a coin ID for
// DigiByte.
func (d *Driver) DecodeCoinID(coinID []byte) (string, error) {
// DigiByte and Bitcoin have the same tx hash and output format.
return (&btc.Driver{}).DecodeCoinID(coinID)
}

// Info returns basic information about the wallet and asset.
func (d *Driver) Info() *asset.WalletInfo {
return WalletInfo
}

// NewWallet is the exported constructor by which the DEX will import the
// exchange wallet. The wallet will shut down when the provided context is
// canceled. The configPath can be an empty string, in which case the standard
// system location of the digibyted config file is assumed.
func NewWallet(cfg *asset.WalletConfig, logger dex.Logger, network dex.Network) (asset.Wallet, error) {
var params *chaincfg.Params
switch network {
case dex.Mainnet:
params = dexdgb.MainNetParams
case dex.Testnet:
params = dexdgb.TestNetParams
case dex.Regtest:
params = dexdgb.RegressionNetParams
default:
return nil, fmt.Errorf("unknown network ID %v", network)
}

// See https://digibyte.org/docs/integrationguide.pdf

// Designate the clone ports. These will be overwritten by any explicit
// settings in the configuration file.
ports := dexbtc.NetPorts{
Mainnet: "14022",
Testnet: "14023",
Simnet: "18443",
}
cloneCFG := &btc.BTCCloneCFG{
WalletCFG: cfg,
MinNetworkVersion: minNetworkVersion,
WalletInfo: WalletInfo,
Symbol: "dgb",
Logger: logger,
Network: network,
ChainParams: params,
Ports: ports,
DefaultFallbackFee: dexdgb.DefaultFee,
DefaultFeeRateLimit: dexdgb.DefaultFeeRateLimit,
LegacyBalance: true,
Segwit: true,
InitTxSize: dexbtc.InitTxSizeSegwit,
InitTxSizeBase: dexbtc.InitTxSizeBaseSegwit,
// UnlockSpends: false, // check listlockunspent after a swap: https://github.com/decred/dcrdex/pull/1558#issuecomment-1096912520
// ConstantDustLimit: dustLimit, // commented to use dexbtc.IsDust, but investigate for DGB
AssetID: BipID,
}

return btc.BTCCloneWallet(cloneCFG)
}
44 changes: 44 additions & 0 deletions client/asset/dgb/regnet_test.go
@@ -0,0 +1,44 @@
//go:build harness

package dgb

// Regnet tests expect the DGB test harness to be running.
//
// Sim harness info:
// The harness has three wallets, alpha, beta, and gamma.
// All three wallets have confirmed UTXOs.
// The beta wallet has only coinbase outputs.
// The alpha wallet has coinbase outputs too, but has sent some to the gamma
// wallet, so also has some change outputs.
// The gamma wallet has regular transaction outputs of varying size and
// confirmation count. Value:Confirmations =
// 10:8, 18:7, 5:6, 7:5, 1:4, 15:3, 3:2, 25:1

import (
"testing"

"decred.org/dcrdex/client/asset/btc/livetest"
"decred.org/dcrdex/dex"
dexbtc "decred.org/dcrdex/dex/networks/btc"
)

var (
tLotSize uint64 = 1e6
tDGB = &dex.Asset{
ID: 20,
Symbol: "dgb",
Version: version,
SwapSize: dexbtc.InitTxSizeSegwit,
SwapSizeBase: dexbtc.InitTxSizeBaseSegwit,
MaxFeeRate: 100,
SwapConf: 1,
}
)

func TestWallet(t *testing.T) {
livetest.Run(t, &livetest.Config{
NewWallet: NewWallet,
LotSize: tLotSize,
Asset: tDGB,
})
}
1 change: 1 addition & 0 deletions client/cmd/dexc/main.go
Expand Up @@ -21,6 +21,7 @@ import (
_ "decred.org/dcrdex/client/asset/bch" // register bch asset
_ "decred.org/dcrdex/client/asset/btc" // register btc asset
_ "decred.org/dcrdex/client/asset/dcr" // register dcr asset
_ "decred.org/dcrdex/client/asset/dgb" // register dgb asset
_ "decred.org/dcrdex/client/asset/doge" // register doge asset
_ "decred.org/dcrdex/client/asset/ltc" // register ltc asset
_ "decred.org/dcrdex/client/asset/zec" // register zec asset
Expand Down
8 changes: 8 additions & 0 deletions client/cmd/dexcctl/simnet-setup.sh
Expand Up @@ -25,6 +25,9 @@ DOGE_ON=$?
~/dextest/zec/harness-ctl/alpha getblockchaininfo > /dev/null
ZEC_ON=$?

~/dextest/dgb/harness-ctl/alpha getblockchaininfo > /dev/null
DGB_ON=$?

set -e

echo initializing
Expand Down Expand Up @@ -63,6 +66,11 @@ if [ $ZEC_ON -eq 0 ]; then
./dexcctl -p abc -p "" --simnet newwallet 133 zcashdRPC ~/dextest/zec/alpha/alpha.conf
fi

if [ $DGB_ON -eq 0 ]; then
echo configuring dgb wallet
./dexcctl -p abc -p "" --simnet newwallet 20 digibytedRPC ~/dextest/dgb/alpha/alpha.conf
fi

echo checking if we have an account already
RESTORING=$(./dexcctl -p abc --simnet discoveracct 127.0.0.1:17273 ~/dextest/dcrdex/rpc.cert)

Expand Down
5 changes: 5 additions & 0 deletions client/cmd/simnet-trade-tests/run
Expand Up @@ -50,6 +50,10 @@ case $1 in
./simnet-trade-tests --base1node trading1 --base2node trading2 --quote doge ${@:2}
;;

dcrdgb)
./simnet-trade-tests --base1node trading1 --base2node trading2 --quote dgb ${@:2}
;;

dcreth)
./simnet-trade-tests --base1node trading1 --base2node trading2 --quote eth ${@:2}
;;
Expand Down Expand Up @@ -80,6 +84,7 @@ ltcdcr - RPC wallets on LTC-DCR market
ltcspvdcr - Litecoin SPV wallet and Decred RPC Wallet on LTC-DCR market
ltcelectrumdcr - Litecoin Electrum wallet and Decred RPC wallet on LTC-DCR market
dcrdoge - RPC wallets on DCR-DOGE market
dcrdgb - RPC wallets on DCR-DGB market
dcreth - Decred RPC wallet and Ethereum native wallet on DCR-ETH market
zecbtc - RPC wallets on ZEC-BTC market
dcrdextt - Decred RPC wallet and Ethereum wallet with dextt.eth test token on market DCR-DEXTT.ETH
Expand Down
37 changes: 31 additions & 6 deletions client/core/simnet_trade.go
Expand Up @@ -38,6 +38,7 @@ import (
"decred.org/dcrdex/client/asset/bch"
"decred.org/dcrdex/client/asset/btc"
"decred.org/dcrdex/client/asset/dcr"
"decred.org/dcrdex/client/asset/dgb"
"decred.org/dcrdex/client/asset/doge"
"decred.org/dcrdex/client/asset/eth"
"decred.org/dcrdex/client/asset/ltc"
Expand All @@ -48,6 +49,7 @@ import (
"decred.org/dcrdex/dex/config"
"decred.org/dcrdex/dex/msgjson"
dexbtc "decred.org/dcrdex/dex/networks/btc"
dexdgb "decred.org/dcrdex/dex/networks/dgb"
dexdoge "decred.org/dcrdex/dex/networks/doge"
dexeth "decred.org/dcrdex/dex/networks/eth"
"decred.org/dcrdex/dex/order"
Expand Down Expand Up @@ -310,7 +312,7 @@ func (s *simulationTest) startClients() error {
// eth needs the headers to be new in order to
// count itself synced, so mining a few blocks here.
hctrl.mineBlocks(s.ctx, 1)
c.log.Infof("Waiting for %s wallet to syn.c", unbip(form.AssetID))
c.log.Infof("Waiting for %s wallet to sync.", unbip(form.AssetID))
synced := make(chan error)
go func() {
tStart := time.Now()
Expand Down Expand Up @@ -626,7 +628,7 @@ sell orders:
}

s.log.Infof("%s\n", `
Placing Clinet 2 Order 1:
Placing Client 2 Order 1:
- Standing order, preimage not revealed, "missed" revoke_order note.
- Expect order status to stay at Epoch status before going AWOL and
to become Revoked after re-connecting the DEX. Locked coins should
Expand Down Expand Up @@ -835,7 +837,10 @@ Client 2 placing Order 3:
// Use core.initialize to restore client 2 orders from db, and login
// to trigger dex authentication.
// TODO: cannot do this anymore with built-in wallets
s.client2.core.initialize()
err = s.client2.core.initialize()
if err != nil {
return fmt.Errorf("client 2 login error: %w", err)
}
err = s.client2.core.Login(s.client2.appPass)
if err != nil {
return fmt.Errorf("client 2 login error: %w", err)
Expand Down Expand Up @@ -1520,7 +1525,7 @@ func (hc *harnessCtrl) fund(ctx context.Context, address string, amts []int) err
func newHarnessCtrl(assetID uint32) *harnessCtrl {

switch assetID {
case dcr.BipID, btc.BipID, ltc.BipID, bch.BipID, doge.BipID, zec.BipID:
case dcr.BipID, btc.BipID, ltc.BipID, bch.BipID, doge.BipID, zec.BipID, dgb.BipID:
return &harnessCtrl{
dir: filepath.Join(dextestDir, dex.BipIDSymbol(assetID), "harness-ctl"),
fundCmd: "./alpha",
Expand Down Expand Up @@ -1555,6 +1560,7 @@ type tWallet struct {
var cloneTypes = map[uint32]string{
0: "bitcoindRPC",
2: "litecoindRPC",
20: "digibytedRPC",
145: "bitcoindRPC", // yes, same as btc
3: "dogecoindRPC",
133: "zcashdRPC",
Expand Down Expand Up @@ -1681,9 +1687,13 @@ func btcCloneWallet(assetID uint32, node string, wt SimWalletType) (*tWallet, er

// doge fees are slightly higher than others. Leaving this as 0 will
// apply bitcoin limits.
if assetID == doge.BipID {
switch assetID {
case doge.BipID:
cfg["fallbackfee"] = fmt.Sprintf("%f", dexdoge.DefaultFee*1000/1e8)
cfg["feeratelimit"] = fmt.Sprintf("%f", dexdoge.DefaultFeeRateLimit*1000/1e8)
case dgb.BipID:
cfg["fallbackfee"] = fmt.Sprintf("%f", dexdgb.DefaultFee*1000/1e8)
cfg["feeratelimit"] = fmt.Sprintf("%f", dexdgb.DefaultFeeRateLimit*1000/1e8)
}

return &tWallet{
Expand All @@ -1697,6 +1707,10 @@ func dogeWallet(node string) (*tWallet, error) {
return btcCloneWallet(doge.BipID, node, WTCoreClone)
}

func dgbWallet(node string) (*tWallet, error) {
return btcCloneWallet(dgb.BipID, node, WTCoreClone)
}

func zecWallet(node string) (*tWallet, error) {
return btcCloneWallet(zec.BipID, node, WTCoreClone)
}
Expand All @@ -1721,6 +1735,8 @@ func (s *simulationTest) newClient(name string, cl *SimClient) (*simulationClien
tw, err = bchWallet(wt, node)
case doge.BipID:
tw, err = dogeWallet(node)
case dgb.BipID:
tw, err = dgbWallet(node)
case zec.BipID:
tw, err = zecWallet(node)
default:
Expand Down Expand Up @@ -2026,9 +2042,18 @@ func (s *simulationTest) assertBalanceChanges(client *simulationClient, isRefund
prevOut := wire.NewOutPoint(&chainhash.Hash{}, 0)
txIn := wire.NewTxIn(prevOut, []byte{}, nil)
msgTx.AddTxIn(txIn)
size := dexbtc.MsgTxVBytes(msgTx)
size := dexbtc.MsgTxVBytes(msgTx) //wut? btc only
// tx fee is 1sat/vByte on simnet. utxoRefundFees is 293 sats.
// TODO: even simnet rate on other assets like dgb and doge isn't 1...
utxoRefundFees := int64(size + dexbtc.RefundSigScriptSize + dexbtc.P2PKHOutputSize)
// TODO: segwit proper fee rate, but need to get segwit flag:
// size := btc.calcTxSize(msgTx)
// if btc.segwit {
// witnessVBytes := uint64((dexbtc.RefundSigScriptSize + 2 + 3) / 4)
// size += witnessVBytes + dexbtc.P2WPKHOutputSize
// } else {
// size += dexbtc.RefundSigScriptSize + dexbtc.P2PKHOutputSize
// }
if ord.Sell {
if accountBIPs[s.base.id] {
baseFees = ethRefundFees
Expand Down
Binary file added client/webserver/site/src/img/coins/dgb.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.