bitcoinj est une bibliothèque Bitcoin pour le langage JVM spécialisée dans le mode SPV.
Cette fois, j'ai traduit environ 1/3 du document bitcoinj "Travailler avec le portefeuille". [^ 1] En lisant ce document, nous pensons que vous approfondirez vos connaissances sur la création de votre propre portefeuille.
Si vous faites une erreur, veuillez la signaler.
Le texte original est ici. Working with the wallet https://bitcoinj.github.io/working-with-the-wallet
Working with the wallet
Découvrez comment utiliser la classe Wallet et créer des transactions personnalisées.
Introduction
La classe Wallet est l'une des classes les plus importantes de bitcoinj et possède les fonctions suivantes.
Afin de créer différents types d'applications, vous devrez apprendre à utiliser Wallet.
Cet article suppose que vous avez lu le livre blanc de Satoshi et Working With Transactions.
Setup
Pour un fonctionnement optimal, le portefeuille doit être connecté à «BlockChain» et à «Peer» ou «PeerGroup». BlockChain est transmis au constructeur du portefeuille, qui peut envoyer et recevoir des blocs liés au portefeuille et extraire les transactions liées au portefeuille (transactions qui envoient et reçoivent des pièces à l'aide de la clé dans le portefeuille). Peer / PeerGroup diffuse les transactions sur le réseau avant que les transactions du portefeuille ne soient incluses dans le bloc.
Le portefeuille commence sans transaction, sans solde, quel que soit son état sur la blockchain. Pour utiliser Wallet, vous devez télécharger la blockchain. Cela chargera la transaction dans votre portefeuille pour analyse et paiement.
Wallet wallet = new Wallet(params);
BlockChain chain = new BlockChain(params, wallet, ...);
PeerGroup peerGroup = new PeerGroup(params, chain);
peerGroup.addWallet(wallet);
peerGroup.startAndWait();
Getting addresses
Bien sûr, les morceaux de code ci-dessus n'ont aucun moyen de se déposer dans le portefeuille et ne sont pas très utiles. Pour obtenir la clé et l'adresse du portefeuille, utilisez l'appel API suivant:
Address a = wallet.currentReceiveAddress();
ECKey b = wallet.currentReceiveKey();
Address c = wallet.freshReceiveAddress();
assert b.toAddress(wallet.getParams()).equals(a);
assert !c.equals(a);
Ceux-ci sont remis pour recevoir le paiement. Le portefeuille a le concept d'une adresse «actuelle». Ceci est pour les portefeuilles GUI qui veulent garder leurs adresses affichées à tout moment. Si l'adresse actuelle est utilisée, elle passera à la nouvelle adresse. La méthode freshReceiveKey / Address, en revanche, renvoie toujours la nouvelle adresse dérivée.
Seeds and mnemonic codes
Les clés et adresses renvoyées par ces méthodes sont dérivées de manière déterministe de la valeur de départ en utilisant les algorithmes spécifiés dans BIP 32 et BIP 39. La durée de vie de la clé est la suivante.
SecureRandom
et sélectionne une entropie aléatoire de 128 bits.Les clés, y compris les valeurs de départ et les clés précalculées, sont stockées sur le disque pour éviter la redéfinition lente des boucles lors du chargement du portefeuille.
Le code mnémonique est conçu pour être plus facile à gérer et à écrire qu'une clé privée brute. Le code mnémonique réduit la possibilité d'erreurs typographiques et permet aux utilisateurs de les écrire facilement avec un stylo ou du papier. Par conséquent, il est recommandé d'exposer le mot à l'utilisateur comme mécanisme de sauvegarde (notez la date pour accélérer la restauration).
Vous pouvez travailler comme suit:
DeterministicSeed seed = wallet.getKeyChainSeed();
println("Seed words are: " + Joiner.on(" ").join(seed.getMnemonicCode()));
println("Seed birthday is: " + seed.getCreationTimeSeconds());
String seedCode = "yard impulse luxury drive today throw farm pepper survey wreck glass federal";
long creationtime = 1409478661L;
DeterministicSeed seed = new DeterministicSeed(seedCode, null, "", creationtime);
Wallet restoredWallet = Wallet.fromSeed(params, seed);
// now sync the restored wallet as described below.
La zone d'anticipation joue un rôle important dans la synchronisation du portefeuille. La taille par défaut de la zone d'anticipation est de 100 clés. Si le portefeuille A est répliqué sur le portefeuille B, le portefeuille A émet 50 clés, et seule la dernière clé est réellement utilisée pour recevoir le paiement, le portefeuille B reconnaît le paiement et se déplace dans la zone d'attente. Et suivez un total de 150 clés. Si Wallet A distribue 120 clés et ne reçoit que le 110e paiement, Wallet B ne sera pas au courant de ce qui s'est passé. Pour cette raison, il est important d'estimer le nombre d'adresses impayées en attente de paiement à un moment donné pour la synchronisation du portefeuille. La valeur par défaut de 100 a été choisie pour convenir au portefeuille du consommateur, mais les scénarios marchands peuvent nécessiter des zones plus grandes.
Replaying the chain
Si vous importez une clé qui a déjà été utilisée dans votre portefeuille, vous devez supprimer la transaction en réinitialisant le portefeuille (en utilisant la méthode reset
) et retéléchargez la chaîne pour obtenir la transaction de la clé ajoutée. .. Pour le moment, il n'y a aucun moyen de jouer à la blockchain dans un portefeuille qui contient déjà des transactions, et si vous essayez cela, vous pouvez corrompre votre portefeuille. Ceci est sujet à changement dans le futur. Vous pouvez également télécharger les données de transaction brutes à partir d'une autre source, telle que Block Explorer, et insérer la transaction directement dans votre portefeuille. Cependant, cela n'est actuellement ni pris en charge ni testé. Pour la plupart des utilisateurs, importer une clé existante est une mauvaise idée et représente une situation où il y a un grave manque de fonctionnalité. Veuillez nous contacter si vous devez importer régulièrement vos clés dans votre portefeuille.
Le portefeuille fonctionne avec d'autres classes du système pour accélérer la synchronisation avec la blockchain, mais par défaut, seules certaines optimisations sont activées. Veuillez lire SpeedingUpChainSync pour comprendre le contenu d'optimisation et la méthode de paramétrage par le portefeuille / PeerGroup.
Creating spends
Après avoir rattrapé la chaîne, vous pouvez dépenser quelques pièces:
System.out.println("You have " + Coin.FRIENDLY_FORMAT.format(wallet.getBalance()));
Les dépenses se composent de 4 étapes.
Pour plus de commodité, il existe des méthodes d'assistance qui exécutent ces étapes. Dans le cas le plus simple:
// Get the address 1RbxbA1yP2Lebauuef3cBiBho853f7jxs in object form.
Address targetAddress = new Address(params, "1RbxbA1yP2Lebauuef3cBiBho853f7jxs");
// Do the send of 1 BTC in the background. This could throw InsufficientMoneyException.
Wallet.SendResult result = wallet.sendCoins(peerGroup, targetAddress, Coin.COIN);
// Save the wallet to disk, optional if using auto saving (see below).
wallet.saveToFile(....);
// Wait for the transaction to propagate across the P2P network, indicating acceptance.
result.broadcastComplete.get();
La méthode sendCoins
renvoie la transaction générée et le ListenableFuture
. ListenableFuture vous permet de bloquer le traitement jusqu'à ce qu'une transaction soit acceptée par le réseau (envoyer à un homologue et recevoir d'un autre). De plus, pour le Future retourné, vous pouvez enregistrer un rappel pour savoir quand la propagation est terminée, enregistrer votre propre TransactionConfidence.Listener
dans la transaction pour surveiller l'état de propagation, ou extraire vous-même. Je peux le faire.
Aux niveaux inférieurs, vous pouvez effectuer vous-même ces étapes:
// Make sure this code is run in a single thread at once.
SendRequest request = SendRequest.to(address, value);
// The SendRequest object can be customized at this point to modify how the transaction will be created.
wallet.completeTx(request);
// Ensure these funds won't be spent again.
wallet.commitTx(request.tx);
wallet.saveToFile(...);
// A proposed transaction is now sitting in request.tx - send it in the background.
ListenableFuture<Transaction> future = peerGroup.broadcastTransaction(request.tx);
// The future will complete when we've seen the transaction ripple across the network to a sufficient degree.
// Here, we just wait for it to finish, but we can also attach a listener that'll get run on a background
// thread when finished. Or we could just assume the network accepts the transaction and carry on.
future.get();
Pour créer une transaction, utilisez d'abord la méthode d'assistance statique de l'objet SendRequest
. Le SendRequest
consiste en un objetTransaction
partiellement invalide qui contient des éléments inchangés tels que les frais, les changements d'adresse et les futures fonctionnalités de confidentialité (telles que les méthodes de sélection de pièces). Vous pouvez modifier des transactions partielles selon vos besoins ou créer vos propres transactions à zéro. La méthode d'assistance statique de SendRequest
est un autre moyen simple de construire une transaction partielle.
Puis complétez la demande. Cela signifie que les transactions de la demande d'envoi ont été ajoutées d'E / S et signées pour valider la transaction. La transaction est désormais acceptée sur le réseau Bitcoin.
Notez qu'aucun verrou n'est maintenu entre completeTx
et commitTx
. Par conséquent, si le portefeuille est modifié en dehors de votre contrôle, ce code peut entrer en conflit et échouer. Par exemple, si la clé de portefeuille est exportée et utilisée ailleurs, et qu'une transaction qui utilise la sortie sélectionnée se produit entre deux appels de méthode. L'utilisation d'une structure simple qui verrouille le portefeuille pendant que les deux opérations sont effectuées peut vous assurer de ne pas engager de doubles dépenses.
When to commit a transaction
Valider une transaction signifie mettre à jour l'indicateur penta du portefeuille afin qu'il ne soit pas réutilisé. Il est important de valider la transaction au bon moment, et il existe différentes stratégies pour le faire.
Le comportement par défaut de sendCoins () est de diffuser après validation. Dans la plupart des cas, c'est un bon choix. Cela signifie que s'il y a un problème avec votre réseau, ou si plusieurs threads essaient de créer et de diffuser une transaction en même temps, vous ne pouvez pas accidentellement doubler vos dépenses. D'un autre côté, si le réseau n'accepte pas la transaction pour quelque raison que ce soit (par exemple, frais insuffisants / formulaire non standard), le portefeuille prend en compte l'argent consommé et vous devez résoudre le problème.
Vous pouvez également utiliser peerGroup.broadcastTransaction
au lieu d'appeler simplement wallet.commitTx
. Une fois qu'une transaction est référencée par plusieurs pairs, la transaction est donnée au portefeuille, puis validée. La principale raison pour laquelle vous souhaitez vous engager après une diffusion réussie est si vous essayez un nouveau code et que vous créez une transaction qui n'est pas toujours acceptable. Dans ce cas, avoir à reculer le portefeuille tout le temps est un problème. Une fois qu'il s'est avéré que le réseau accepte toujours les transactions, vous pouvez créer et terminer des demandes d'envoi et valider les résultats des transactions, le tout sous un seul verrou. Ainsi, plusieurs threads ne généreront pas accidentellement une double dépense.
[^ 1]: Je voulais vraiment tout traduire, mais c'était trop long et j'ai échoué.
Recommended Posts