dcrwallet e dcrctl

11 minutos de leitura

1. Introdução

O uso de uma solução dcrwallet + dcrctl é útil para usuários avançados que:

a) querem usar funcionalidades que já existem no Decrediton, mas precisam especificar parâmetros e valores fora do suportado pelo Decrediton;

b) querem testar ou usar funcionalidades que ainda não foram construídas dentro do Decrediton;

c) estão desenvolvendo novos dispositivos, ferramentas e funcionalidades para o Decred

Saiba mais sobre a estrutura do Decred.

2. Uso comum do dcrwallet e dcrctl

Todos os comandos a seguir foram executados na Testnet. Para executá-los na Mainnet baster remover a opção --testnet.

2.1. Criação da carteira

Se ainda não possui uma carteira no diretório do $HOME/.dcrwallet deve primeiro criar uma.

$ ./dcrwallet --testnet --create

Ao iniciar o dcrwallet a primeira coisa a fazer é definir e confirmar a senha que irá proteger a chave privada.

Enter the private passphrase for your new wallet:
Confirm passphrase:

Em seguida o dcrwallet perguntará se deseja encriptar as informações públicas (transações e endereços).

Do you want to add an additional layer of encryption for public data? (n/no/y/yes) [no]:

O uso dessa senha para encriptar informações públicas é opcional. Com ela, caso seu wallet.db seja copiado, um atacante não poderá conectar você às suas transações por não saber quanto, quando e em que seus DCRs foram gastos.

O usuário será então perguntado se já possui uma seed existente que gostaria de usar.

Do you have an existing wallet seed you want to use? (n/no/y/yes) [no]:

Se disser que não será criada uma nova seed. Se disser que sim o dcrwallet pedirá que digite a seed existente. Não utilize uma seed em mais de uma carteira. Saiba mais no artigo Uma seed, uma carteira. Ao criar uma nova seed o dcrwallet gera um alerta:

IMPORTANTE: Mantenha a seed em um lugar seguro pois você não poderá restaurar a carteira sem ela. Tenha em mente que qualquer um que tenha acesso a seed pode restaurar a sua carteira e ter acesso aos seus fundos então é fundamental que a mantenha em um local seguro. Assim que tiver armazenado a seed em um local seguro, digite “OK” para continuar:

Digite OK e pressione Enter. A carteira estará criada. Abra outro terminal e execute o dcrd na Testnet. É possível guardar a blockchain da Testnet em uma partição ou disco diferente de onde a blockchain da Mainnet está guardada usando a opção -b. Minimize o terminal. O dcrd continuará a ser executado nele.

$ ./dcrd --testnet -b /opt/blockchain-testnet --addrindex

Assim que o dcrd estiver pronto, volte ao primeiro terminal e inicie o dcrwallet, agora sem a opção --create:

$ ./dcrwallet --testnet

Na primeira execução o dcrwallet precisará da senha carteira para acessar a chave privada e derivar as chaves públicas. Essas chaves são os endereços de transferências procurados na blockchain. Essa procura consta no output do dcrwallet como:

[INF] WLLT: Rescanning blocks 000001-002000...

Quando o dcrwallet estiver pronto seu terminal mostrará uma sequência de linhas com o seguinte formato:

[INF] SYNC: Blockchain sync completed, wallet ready for general usage.
[INF] WLLT: Connecting block $BLOCK_HEX_NUMBER, height $BLOCK_NUMBER

Minimize também esse terminal. O dcrwallet continuará a ser executado nele.

2.1.1. Carteira com senha para informações públicas

Se a carteira foi criada com uma encriptação de informações públicas será necessário informá-la na execução do dcrwallet:

$ ./dcrwallet --testnet

[ERR] DCRW: Failed to open wallet: invalid passphrase for master public key

$ ./dcrwallet --testnet --walletpass=$PUBLICPASSWORD

[INF] DCRW: Version 1.1.2+release (Go version go1.9.2)
[INF] WLLT: Opened wallet
*** ATTENTION ***
Since this is your first time running we need to sync accounts. Please enter
the private wallet passphrase. This will complete syncing of the wallet
accounts and then leave your wallet unlocked. You may relock wallet after by
calling 'walletlock' through the RPC.
*****************
Enter private passphrase:

2.2. Cópia da carteira (wallet.db)

Atenção! Usar o mesmo arquivo wallet.db no dcrwallet e no Decrediton é o mesmo que usar uma seed em duas carteiras ao mesmo tempo. Use o dcrwallet e o Decrediton alternadamente, copiando a carteira entre os aplicativos.

2.2.1. Cópia da carteira do Decrediton para o dcrwallet

Se a sua carteira foi criada no Decrediton é possível copiá-la para uso no dcrwallet. No Linux, se estiver usando os diretórios na configuração default:

$ cp ~/.config/decrediton/testnet2/wallet.db ~/.dcrwallet/testnet2/

Para a Mainnet substitua testnet2 por mainnet.

2.2.2. Cópia da carteira do dcrwallet para o Decrediton

Também é possível copiar a carteira criada no dcrwallet para o Decrediton, mesmo que a carteira tenha senha para informações públicas. Apesar de não criar carteiras com essa senha, o Decrediton suporta o seu uso.

Figura 1 - Decrediton pede a senha para informações públicas
Figura 1 - Decrediton pede a senha para informações públicas

Apesar disso, a aba Settings do Decrediton só permite a atualização da senha da chave privada.

2.3. Troca de senha, listagem e saldo de contas

Abra um novo terminal. De agora em diante o componente usado será o dcrctl, que é um cliente RPC que se conecta tanto ao dcrwallet como ao dcrd.

Para ver todas as opções suportadas pelo dctctl (primeira linha) e os comandos suportados pelo dcrd e dcrwallet (segunda linha):

$ ./dcrctl --help
$ ./dcrctl -l

O dcrctl se conecta ao dcrwallet com a opção --wallet e ao dcrd sem essa opção. Por exemplo, para saber o último bloco conhecido pelo dcrd:

$ ./dcrctl --testnet getblockcount

252218

É possível trocar a senha da chave privada da carteira, não das informações públicas:

$./dcrctl --testnet --wallet walletpassphrasechange $OLDPASSWORD $NEWPASSWORD

Isso significa que, para poder trocar ou apagar a senha pública será necessário apagar a carteira, o arquivo wallet.db, e recriar a carteira a partir da seed.

Para obter uma visão geral da carteira:

$ ./dcrctl --testnet --wallet walletinfo

{
  "daemonconnected": true,
  "unlocked": false,
  "txfee": 0.001,
  "ticketfee": 0.001,
  "ticketpurchasing": false,
  "votebits": 1,
  "votebitsextended": "06000000",
  "voteversion": 6,
  "voting": false
}

Para uma lista simples de contas:

$ ./dcrctl --testnet --wallet listaccounts

{
  "default": 0.1,
  "imported": 0
}

Para obter um saldo mais detalhado por conta:

$ ./dcrctl --testnet --wallet getbalance

{
  "balances": [
    {
      "accountname": "default",
      "immaturecoinbaserewards": 0,
      "immaturestakegeneration": 0,
      "lockedbytickets": 0,
      "spendable": 0.1,
      "total": 0.1,
      "votingauthority": 0
    },
    {
      "accountname": "imported",
      "immaturecoinbaserewards": 0,
      "immaturestakegeneration": 0,
      "lockedbytickets": 0,
      "spendable": 0,
      "total": 0,
      "unconfirmed": 0,
      "votingauthority": 0
    }
  ],
  "blockhash": "0000000005574d01e73241ce5b33f90b453cd7727149f6fd5e73a909d9e6295"
}

2.4. Endereço para recebimento

Para receber uma transferência nessa carteira é necessário gerar um endereço e envia-lo a outra parte.

$ ./dcrctl --testnet --wallet getnewaddress

TsXB3MndDeG6PToFw5PvBdHEJcMXCEBhG8y

Esse endereço de recebimento será usado para receber uma transferência a partir da conta criada para Bob no artigo Testando o Decred na Testnet. O envio será feito da conta de Alice.

Figura 2 - Alice envia 0.2 DCR para Bob
Figura 2 - Alice envia 0.2 DCR para Bob

2.5. Lista de transações

Após receber uma transferência ainda não confirmada, o saldo mostrará essa informação como “unconfirmed”:

$ ./dcrctl --testnet --wallet getbalance

{
  "balances": [
    {
      "accountname": "default",
      "immaturecoinbaserewards": 0,
      "immaturestakegeneration": 0,
      "lockedbytickets": 0,
      "spendable": 0.1,
      "total": 0.3,
      "unconfirmed": 0.2,
      "votingauthority": 0
    },
(...)

Para listar as transações feitas tendo essa carteira como origem ou destino:

$ ./dcrctl --testnet --wallet listtransactions

[
  {
    "account": "default",
    "address": "TsSR4yrDHNAAbt62uTntutroCAtnNBw9cUo",
    "amount": 0.1,
    "blockhash": "00000000003839d732291a96d4d8dd226cbe7ce9714f80ea93f477e0653cf47c",
    "blocktime": 1519934278,
    "category": "receive",
    "confirmations": 2804,
    "time": 1519934233,
    "timereceived": 1519934233,
    "txid": "4a103798cdaee813f79254b421038edf3e555fe4ccdc8639cb6786a85eece475",
    "txtype": "regular",
    "vout": 0,
    "walletconflicts": []
  },
  {
    "account": "default",
    "address": "TsXB3MndDeG6PToFw5PvBdHEJcMXCEBhG8y",
    "amount": 0.2,
    "blockhash": "0000000000ef152e0181979a2f3ff1018d28953ffaf54cfcc49967302b2ca086",
    "blocktime": 1520273284,
    "category": "receive",
    "confirmations": 3,
    "time": 1520273217,
    "timereceived": 1520273217,
    "txid": "b06008f559a90706ebf4dffea3848c2d96010cd97b559c4c1fccee7f063b80e6",
    "txtype": "regular",
    "vout": 0,
    "walletconflicts": []
  }
]

2.6. Envio de recursos

Agora será feito o processo inverso: a conta de Bob enviará 0.05 DCR para a conta de Alice.

Figura 3 - Bob envia 0.05 DCR para Alice
Figura 3 - Bob envia 0.05 DCR para Alice

$ ./dcrctl --testnet --wallet sendtoaddress "Tsn7ERfzp8y4B3kJ1MA3c167eWeZSHSZS28" 0.05

-13: Enter the wallet passphrase with walletpassphrase first

O dcrctl se conecta com o dcrwallet para fazer a transferência mas a senha da chave privada é necessária para destravar a carteira.

$ ./dcrctl --testnet --wallet walletpassphrase $PASSWORD 30

Após destravar a carteira, no terminal onde o dcrwallet é executado haverá a seguinte informação:

[INF] WLLT: The wallet has been temporarily unlocked

Execute novamente o comando. O dcrctl responde com o ID da transação (txid).

$ ./dcrctl --testnet --wallet sendtoaddress "Tsn7ERfzp8y4B3kJ1MA3c167eWeZSHSZS28" 0.05

270bc9b154b1a7a16d4e651d4dc1d4954b79f8f8aa429c95f988803b6e08040d

Com esse txid é possível consultar mais informações no dcrwallet:

$ ./dcrctl --testnet --wallet gettransaction 270bc9b154b1a7a16d4e651d4dc1d4954b79f8f8aa429c95f988803b6e08040d

{
  "amount": 0,
  "fee": -0.000253,
  "confirmations": 2,
  "blockhash": "00000000067409c8326217f823084f4532babbc603429d05f5b3297ee90a8362",
  "blockindex": 0,
  "blocktime": 1520279280,
  "txid": "270bc9b154b1a7a16d4e651d4dc1d4954b79f8f8aa429c95f988803b6e08040d",
  "walletconflicts": [],
  "time": 1520279087,
  "timereceived": 1520279087,
  "details": [
    {
      "account": "",
      "amount": -0.1,
      "category": "send",
      "fee": -0.000253,
      "vout": 0
    }
  ],
  "hex": "010000000175e4ec5ea88667cb3986dccce45f553edf8e0321b45492f713e8aecd9837104a0000000000ffffffff02404b4c000000000000001976a914e751b032642fa1adf0827a3904143dac71bff91788ac6ce84b000000000000001976a9146646c16d3b1474037ede9af7ae137634105771bc88ac000000000000000001ffffffffffffffff00000000ffffffff6a47304402207cc60b8234152eaea644c8026a68cbf2c8e16d37e6492a34d0e7c9232cf79026022072b28e53aadda7ecb7da925ee37d517eaafb038850c84665b1cb9420d0458c5e012102f4a2eb35d74037d29da1e100b3c4f52a3c53f881761faff4238f6c8519f75f8d"
}

Caso tenha destravado a carteira por um tempo muito longo, é possível travá-la novamente. O resultado pode ser visto na execução do dcrwallet logo em seguida.

$ ./dcrctl --testnet --wallet walletlock

[INF] WLLT: The wallet has been locked.

Cerca de 24 horas após o envio, listamos as transações na carteira de Bob mais uma vez:

$ ./dcrctl --testnet --wallet listtransactions

[
  {
    "account": "default",
    "address": "TsSR4yrDHNAAbt62uTntutroCAtnNBw9cUo",
    "amount": 0.1,
    "blockhash": "00000000003839d732291a96d4d8dd226cbe7ce9714f80ea93f477e0653cf47c",
    "blocktime": 1519934278,
    "category": "receive",
    "confirmations": 3528,
    "time": 1519934233,
    "timereceived": 1519934233,
    "txid": "4a103798cdaee813f79254b421038edf3e555fe4ccdc8639cb6786a85eece475",
    "txtype": "regular",
    "vout": 0,
    "walletconflicts": []
  },
  {
    "account": "default",
    "address": "TsXB3MndDeG6PToFw5PvBdHEJcMXCEBhG8y",
    "amount": 0.2,
    "blockhash": "0000000000ef152e0181979a2f3ff1018d28953ffaf54cfcc49967302b2ca086",
    "blocktime": 1520273284,
    "category": "receive",
    "confirmations": 727,
    "time": 1520273217,
    "timereceived": 1520273217,
    "txid": "b06008f559a90706ebf4dffea3848c2d96010cd97b559c4c1fccee7f063b80e6",
    "txtype": "regular",
    "vout": 0,
    "walletconflicts": []
  },
  {
    "account": "",
    "address": "Tsn7ERfzp8y4B3kJ1MA3c167eWeZSHSZS28",
    "amount": -0.05,
    "blockhash": "00000000067409c8326217f823084f4532babbc603429d05f5b3297ee90a8362",
    "blocktime": 1520279280,
    "category": "send",
    "confirmations": 686,
    "fee": -0.000253,
    "time": 1520279087,
    "timereceived": 1520279087,
    "txid": "270bc9b154b1a7a16d4e651d4dc1d4954b79f8f8aa429c95f988803b6e08040d",
    "txtype": "regular",
    "vout": 0,
    "walletconflicts": []
  }
]

A lista mostra três transações: a primeira foi feita no artigo Enviando e recebendo DCRs via Decrediton, a segunda neste artigo na seção 2.5 e a terceira nesta seção.

Para o usar o dcrctl para consultar o dcrd sobre transações para o endereço para o qual fizemos o envio:

$ ./dcrctl --testnet searchrawtransactions Tsn7ERfzp8y4B3kJ1MA3c167eWeZSHSZS28

[
  {
    "hex": "010000000175e4ec5ea88667cb3986dccce45f553edf8e0321b45492f713e8aecd9837104a0000000000ffffffff02404b4c000000000000001976a914e751b032642fa1adf0827a3904143dac71bff91788ac6ce84b000000000000001976a9146646c16d3b1474037ede9af7ae137634105771bc88ac00000000000000000180969800000000002bd10300030000006a47304402207cc60b8234152eaea644c8026a68cbf2c8e16d37e6492a34d0e7c9232cf79026022072b28e53aadda7ecb7da925ee37d517eaafb038850c84665b1cb9420d0458c5e012102f4a2eb35d74037d29da1e100b3c4f52a3c53f881761faff4238f6c8519f75f8d",
    "txid": "270bc9b154b1a7a16d4e651d4dc1d4954b79f8f8aa429c95f988803b6e08040d",
    "version": 1,
    "locktime": 0,
    "vin": [
      {
        "txid": "4a103798cdaee813f79254b421038edf3e555fe4ccdc8639cb6786a85eece475",
        "vout": 0,
        "tree": 0,
        "amountin": 0.1,
        "blockheight": 250155,
        "blockindex": 3,
        "scriptSig": {
          "asm": "304402207cc60b8234152eaea644c8026a68cbf2c8e16d37e6492a34d0e7c9232cf79026022072b28e53aadda7ecb7da925ee37d517eaafb038850c84665b1cb9420d0458c5e01 02f4a2eb35d74037d29da1e100b3c4f52a3c53f881761faff4238f6c8519f75f8d",
          "hex": "47304402207cc60b8234152eaea644c8026a68cbf2c8e16d37e6492a34d0e7c9232cf79026022072b28e53aadda7ecb7da925ee37d517eaafb038850c84665b1cb9420d0458c5e012102f4a2eb35d74037d29da1e100b3c4f52a3c53f881761faff4238f6c8519f75f8d"
        },
        "sequence": 4294967295
      }
    ],
    "vout": [
      {
        "value": 0.05,
        "n": 0,
        "version": 0,
        "scriptPubKey": {
          "asm": "OP_DUP OP_HASH160 e751b032642fa1adf0827a3904143dac71bff917 OP_EQUALVERIFY OP_CHECKSIG",
          "hex": "76a914e751b032642fa1adf0827a3904143dac71bff91788ac",
          "reqSigs": 1,
          "type": "pubkeyhash",
          "addresses": [
            "Tsn7ERfzp8y4B3kJ1MA3c167eWeZSHSZS28"
          ]
        }
      },
      {
        "value": 0.049747,
        "n": 1,
        "version": 0,
        "scriptPubKey": {
          "asm": "OP_DUP OP_HASH160 6646c16d3b1474037ede9af7ae137634105771bc OP_EQUALVERIFY OP_CHECKSIG",
          "hex": "76a9146646c16d3b1474037ede9af7ae137634105771bc88ac",
          "reqSigs": 1,
          "type": "pubkeyhash",
          "addresses": [
            "TsaLvAJwAMD6Ez8KSVPSVQTDszBKijExkt5"
          ]
        }
      }
    ],
    "blockhash": "00000000067409c8326217f823084f4532babbc603429d05f5b3297ee90a8362",
    "confirmations": 687,
    "time": 1520279280,
    "blocktime": 1520279280
  }
]

Essa transação tem um endereço “vin” e dois endereços “vout”. Como se pode perceber, temos aí “in” e “out”, entrada e saída. O endereço vin é o recebimento de DCR que ocorreu no endereço TsSR4yrDHNAAbt62uTntutroCAtnNBw9cUo dessa carteira no artigo Testando o Decred na Testnet. Esse input será gasto agora. É a origem do dinheiro dessa transação. Quanto aos endereços vout, o primeiro é o envio de 0.05 DCR para Tsn7ERfzp8y4B3kJ1MA3c167eWeZSHSZS28 e o segundo é o endereço de troco, porque afinal, apenas 0.05 DCR de 0.1 DCR foi gasto. Resta ainda incluir no cálculo a taxa (fee) que foi para a transação, de 0.000253 DCR (demonstrado no output do comando listtransactions).

vin = vout(1) + vout(2) + fee 0.1 DCR = 0.05 DCR + 0.049747 DCR + 0.000253 DCR

2.7. Listar inputs não gastos e consolidação

Para listar todos os inputs não gastos nessa carteira:

$ ./dcrctl --testnet --wallet listunspent

[
  {
    "txid": "270bc9b154b1a7a16d4e651d4dc1d4954b79f8f8aa429c95f988803b6e08040d",
    "vout": 1,
    "tree": 0,
    "txtype": 0,
    "address": "TsaLvAJwAMD6Ez8KSVPSVQTDszBKijExkt5",
    "account": "default",
    "scriptPubKey": "76a9146646c16d3b1474037ede9af7ae137634105771bc88ac",
    "amount": 0.049747,
    "confirmations": 741,
    "spendable": true
  },
  {
    "txid": "b06008f559a90706ebf4dffea3848c2d96010cd97b559c4c1fccee7f063b80e6",
    "vout": 0,
    "tree": 0,
    "txtype": 0,
    "address": "TsXB3MndDeG6PToFw5PvBdHEJcMXCEBhG8y",
    "account": "default",
    "scriptPubKey": "76a91443803a23063e5cd2c53c1a00aee68605614dcbd388ac",
    "amount": 0.2,
    "confirmations": 782,
    "spendable": true
  }
]

A lista acima mostra duas transações: a primeira é troco gerado pelo envio de 0.05 DCR na seção 2.6 e a segunda é o recebimento de 0.2 DCR para o endereço gerado na seção 2.4 com recebimento ocorrendo na seção 2.5.

É possível consolidar os inputs em um único (é necessário pagar uma fee pois essa transação ocorrerá na blockchain). Essa consolidação reduz o número de inputs, fazendo com que o tamanho de outras transações fique menor (e mais baratas).

$ ./dcrctl --testnet --wallet consolidate inputs

2.8. Assinatura digital

Para usar o dcrwallet para assinar uma mensagem primeiro é preciso destravar a carteira. O comando a seguir usa a senha da carteira para destravá-la por 30 segundos.

$ ./dcrctl --testnet --wallet walletpassphrase $PASSWORD 30

Após destravar a carteira é possível usar a chave privada e assinar a mensagem. O dcrctl devolve o “digest” da assinatura.

$ ./dcrctl --testnet --wallet signmessage "TsSR4yrDHNAAbt62uTntutroCAtnNBw9cUo" "#235711"

IHu4nBrCkRJkEX5ap8F0Lm4lEn1Fdh+/+fxmk+lQCVTCeqVrkMbLTgsh5Sww5iP4QZPLu5wdrLJxBUAT9WVWMsM=

Para verificar a assinatura da mensagem, a outra parte pode acessar https://testnet.decred.org/messages/verify.

Figura 4 - Verificação da mensagem assinada em decred.org
Figura 4 - Verificação da mensagem assinada em decred.org

2.9. Criação de novas contas e alteração de nome

É possivel criar e renomear contas via dcrctl. Para saber mais sobre contas veja o artigo Geração de chaves no Decred.

$ ./dcrctl --testnet --wallet createnewaccount
$ ./dcrctl --testnet --wallet renameaccount $OLDNAME $NEWNAME

2.10. Terminar a execução do dcrd e do dcrwallet

Os comandos a seguir encerram, via RPC, a execução do dcrd e do dcrwallet. Sem esses comandos seria necessário abrir os terminais minimizados onde ocorrem as execuções e encerrá-las com Ctrl+C.

$ ./dcrctl --testnet stop
[INF] DCRD: Shutdown requested.  Shutting down...
[INF] DCRD: Gracefully shutting down the server...
[WRN] SRVR: Server shutting down
[WRN] RPCS: RPC server shutting down
[ERR] RPCS: Websocket receive error from (...) use of closed network connection
[INF] RPCS: RPC server shutdown complete
[INF] BMGR: Block manager shutting down
[INF] AMGR: Address manager shutting down
[INF] SRVR: Server shutdown complete
[INF] DCRD: Gracefully shutting down the database...
[INF] RPCS: Disconnected websocket client [::1]:41704
[INF] DCRD: Shutdown complete

$ ./dcrctl --testnet --wallet stop
[INF] RPCS: RPC method getbalance invoked by client 127.0.0.1:65346
[INF] RPCS: RPC method stop invoked by client 127.0.0.1:65349
[INF] DCRW: Shutdown requested.  Shutting down...
[WRN] DCRW: Stopping JSON-RPC server...
[INF] DCRW: JSON-RPC server shutdown
[WRN] DCRW: Stopping gRPC server...
[INF] DCRW: gRPC server shutdown
[INF] DCRW: Closed wallet

3. Exclusão da carteira

Veja detalhes no artigo Excluindo a carteira.