This article will introduce how to use blockchain to trade .
【 This article forbids any form of full text paste reprint , This article is from zacky31 The essay of 】
The goal is :
stay Last article in , We've created a trusted blockchain . But at present, the chain created contains less useful information . today , I'm going to replace the previous with trading information data Content , I'm going to create a simple cryptocurrency , called “noobcoin”.
Premise :
- I have learned the basic knowledge of blockchain
- be used GSON and bounceycastle
Let's get started
In cryptocurrencies , The ownership of money will be transferred by way of transaction , People involved in the transaction will have an address , Used to send and receive transaction amounts .
Upper figure , It reflects a transaction process .
First , We create a Wallet class , It is used to store public key and private key .
import java.security.PrivateKey;
import java.security.PublicKey; public class Wallet {
public PrivateKey privateKey;
public PublicKey publicKey; }
that , What are the public key and private key used for ?
Actually , The public key is the address we need for money . In the course of each transaction can be shared with the trading party . Our private key is used to encrypt every transaction , This ensures that people with private keys can trade . The private key can only be said to know ! meanwhile , The public key is passed to the trading party along with the transaction , Can be used to verify the signature , Determine whether the data has been tampered with .
Next , You need to generate key value pairs of public key and private key . I'm going to use elliptic curve cryptography to generate . Let's revise it Wallet Class .
import java.security.*;
import java.security.spec.ECGenParameterSpec; public class Wallet {
public PrivateKey privateKey;
public PublicKey publicKey; public Wallet() {
generateKeyPair();
} private void generateKeyPair() {
try {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ECDSA", "BC");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
ECGenParameterSpec ecSpec = new ECGenParameterSpec("prime192v1");
keyGen.initialize(ecSpec, random);
KeyPair keyPair = keyGen.generateKeyPair(); privateKey = keyPair.getPrivate();
publicKey = keyPair.getPublic();
} catch (Exception e) {
throw new RuntimeException(e);
}
} public static void main(String[] args) {
Wallet wallet = new Wallet();
System.out.println(wallet.publicKey);
System.out.println(wallet.privateKey);
}
}
up to now , We've created the wallet , Think about how to design a deal .
In every transaction , You need to carry some data :
- The payer's public key
- The payee's public key
- Transaction amount
- Input , Previous trading references , Prove that the payer has the funds to carry out the transaction
- Output , Display the relevant address received in this transaction
- Encrypted signature , It is used to prove that the data has not been tampered in the process of transaction
Then go and create a Transaction Class .
import java.security.PublicKey;
import java.util.ArrayList; public class Transcation {
public String transcationId;
public PublicKey sender;
public PublicKey reciepient;
public float value;
public byte[] signature; public ArrayList<TranscationInput> inputs = new ArrayList<TranscationInput>();
public ArrayList<TranscationOutput> outputs = new ArrayList<TranscationOutput>(); private static int sequence = 0; public Transcation(PublicKey from, PublicKey to, float value, ArrayList<TranscationInput> inputs) {
this.sender = from;
this.reciepient = to;
this.value = value;
this.inputs = inputs;
} private String calulateHash() {
sequence++;
return StringUtil.applySha256(
StringUtil.getStringFromKey(sender) +
StringUtil.getStringFromKey(reciepient) +
Float.toString(value) + sequence
);
} }
So far, , The program will report an error , For a while , I'm going to create TransactionInput class and TransactionOutput class . meanwhile , The transaction class needs to include methods for generating and verifying signatures and methods for verifying transactions . however , All of these have to wait a moment .
Consider the purpose of the signature and how it works ?
Signature plays two important roles in blockchain : First , The signature guarantees the payer's consumption ; secondly , Preventing others from tampering with transactions that have taken place . This is using the private key to encrypt data , Public key to verify its reliability .
Let's start doing these things . Before that , stay StringUtils Class , Add two methods .applyECDSASig() Used to generate signatures ,verifyECDSASig() To verify the signature .
public static byte[] applyECDSASig(PrivateKey privateKey, String input) {
Signature dsa;
byte[] output = new byte[0];
try {
dsa = Signature.getInstance("ECDSA", "BS");
dsa.initSign(privateKey);
byte[] strByte = input.getBytes();
dsa.update(strByte);
byte[] realSig = dsa.sign();
output = realSig;
} catch (Exception e) {
throw new RuntimeException(e);
}
return output;
} public static boolean verifyECDSASig(PublicKey publicKey,String data,byte[] signature){
try{
Signature ecdsaVerify = Signature.getInstance("ECDSA","BC");
ecdsaVerify.initVerify(publicKey);
ecdsaVerify.update(data.getBytes());
return ecdsaVerify.verify(signature);
}catch (Exception e){
throw new RuntimeException(e);
}
} public static String getStringFromKey(Key key){
return Base64.getEncoder().encodeToString(key.getEncoded());
}
next , Just use the method in the tool class , stay Transaction Class generateSignature() and verifiySignatur() Method .
public void generateSignature(PrivateKey privateKey) {
String data = StringUtil.getStringFromKey(sender) + StringUtil.getStringFromKey(reciepient);
signature = StringUtil.applyECDSASig(privateKey, data);
} public boolean verfiySignature() {
String data = StringUtil.getStringFromKey(sender) + StringUtil.getStringFromKey(reciepient);
return StringUtil.verifyECDSASig(sender, data, signature);
}
It's more than half done , Go first Chain Class to test it .
import org.bouncycastle.jce.provider.BouncyCastleProvider; import java.security.Security;
import java.util.ArrayList; public class Chain {
public static ArrayList<Block> blockChain = new ArrayList<>();
public static int difficulty = 5;
public static Wallet walletA;
public static Wallet walletB; public static void main(String[] args) {
Security.addProvider(new BouncyCastleProvider());
walletA = new Wallet();
walletB = new Wallet(); System.out.println("Private and Public keys:");
System.out.println(StringUtil.getStringFromKey(walletA.privateKey));
System.out.println(StringUtil.getStringFromKey(walletA.publicKey)); Transcation transcation = new Transcation(walletA.publicKey, walletB.publicKey, 5, null);
transcation.generateSignature(walletA.privateKey); System.out.println("Is signature verified");
System.out.println(transcation.verfiySignature());
}
}
We can see , Successfully generated Private key and Public key , And be able to verify the authenticity .
Consider such a scenario , When you have a bitcoin , You have to have received a bitcoin before , Bitcoin's ledger doesn't add a bitcoin to your account or subtract a bitcoin from the consumer , The consumer can only point to a bitcoin that he or she has previously accepted , So a transaction output is created to show the address a bitcoin sent to you ( The input of the transaction points to the output of the previous transaction ).
Starting from this point , We'll follow the instructions in bitcoin , All unused transaction outputs are called UTXO.
So create a TransactionInput class .
public class TransactionInput {
public String transactionOutputId;
public TransactionOutput UTXO; public TransactionInput(String transactionOutputId) {
this.transactionOutputId = transactionOutputId;
}
}
as well as TransactionOutputs class . The output of the transaction will show the final amount sent to each party from the transaction , So it is referenced in the new transaction and not entered , As proof of the amount you can send .
import java.security.PublicKey; public class TransactionOutput {
public String id;
public PublicKey reciepient;
public float value;
public String parentTransactionId; public TransactionOutput(PublicKey reciepient, float value, String parentTransactionId) {
this.reciepient = reciepient;
this.value = value;
this.parentTransactionId = parentTransactionId;
this.id = StringUtil.applySha256(StringUtil.getStringFromKey(reciepient)+Float.toString(value)+parentTransactionId);
} public boolean isMine(PublicKey publicKey) {
return (publicKey == reciepient);
}
}
Blocks in the chain will receive a lot of transaction information , So the blockchain will be very, very long , It takes a long time to process a new transaction because we have to look for and check its input , To get around this, we save an extra set called used transactions as available inputs , So adding a set to the main function is called UTXO.
Now revise it Transaction class . Add ways to process transactions .
public boolean processTransaction() { if(verifySignature() == false) {
System.out.println("#Transaction Signature failed to verify");
return false;
} for(TransactionInput i : inputs) {
i.UTXO = Chain.UTXOs.get(i.transactionOutputId);
} if(getInputsValue() < Chain.minimumTransaction) {
System.out.println("Transaction Inputs too small: " + getInputsValue());
System.out.println("Please enter the amount greater than " + Chain.minimumTransaction);
return false;
} float leftOver = getInputsValue() - value;
transactionId = calulateHash();
outputs.add(new TransactionOutput( this.reciepient, value,transactionId));
outputs.add(new TransactionOutput( this.sender, leftOver,transactionId)); for(TransactionOutput o : outputs) {
Chain.UTXOs.put(o.id , o);
} for(TransactionInput i : inputs) {
if(i.UTXO == null) continue;
Chain.UTXOs.remove(i.UTXO.id);
} return true;
} public float getInputsValue() {
float total = 0;
for(TransactionInput i : inputs) {
if(i.UTXO == null) continue;
total += i.UTXO.value;
}
return total;
}
In this method, we perform some checks to make sure the transaction is valid , We collect input to produce output , most important of all , At the end of the feeding , We abandoned the input in our UTXO list , This means that an available transaction output must be input before it can be used , So the input value must be fully used , So payers have to change their own amount status . This is very similar to our actual situation , When you give 5 Yuan and then spent 1 element , I'll find you 4 element .
Last , Update Wallet , Add methods to get balance, etc . You are free to add some other features to your wallet , For example, keep a history of your transactions and so on .
public float getBalance() {
float total = 0;
for (Map.Entry<String, TransactionOutput> item: Chain.UTXOs.entrySet()){
TransactionOutput UTXO = item.getValue();
if(UTXO.isMine(publicKey)) {
UTXOs.put(UTXO.id,UTXO);
total += UTXO.value ;
}
}
return total;
} public Transaction sendFunds(PublicKey _recipient,float value ) {
if(getBalance() < value) {
System.out.println("#Not Enough funds to send transaction. Transaction Discarded.");
return null;
}
ArrayList<TransactionInput> inputs = new ArrayList<TransactionInput>(); float total = 0;
for (Map.Entry<String, TransactionOutput> item: UTXOs.entrySet()){
TransactionOutput UTXO = item.getValue();
total += UTXO.value;
inputs.add(new TransactionInput(UTXO.id));
if(total > value) break;
} Transaction newTransaction = new Transaction(publicKey, _recipient , value, inputs);
newTransaction.generateSignature(privateKey); for(TransactionInput input: inputs){
UTXOs.remove(input.transactionOutputId);
} return newTransaction;
}
Now? , There's already a trading system , It needs to be put in the blockchain . We replace some useless information in the block with a list of transactions , But in a single block there may be 1000 A deal , This leads to a lot of hash Calculation , Don't worry, we're using trading here merkle Trees , You'll see later . Let's add a help method to create merkleroot stay StringUtils Class
public static String getMerkleRoot(ArrayList<Transaction> transactions) {
int count = transactions.size();
ArrayList<String> previousTreeLayer = new ArrayList<>();
for (Transaction transaction : transactions) {
previousTreeLayer.add(transaction.transactionId);
}
ArrayList<String> treeLayer = previousTreeLayer;
while (count > 1) {
treeLayer = new ArrayList<>();
for (int i = 1; i < previousTreeLayer.size(); i++) {
treeLayer.add(applySha256(previousTreeLayer.get(i - 1) + previousTreeLayer.get(i)));
}
count = treeLayer.size();
previousTreeLayer = treeLayer;
}
String merkleRoot = (treeLayer.size() == 1) ? treeLayer.get(0) : "";
return merkleRoot;
} public static String getDificultyString(int difficulty) {
return new String(new char[difficulty]).replace('\0', '0');
}
Block The class code is as follows :
import java.util.ArrayList;
import java.util.Date; public class Block { public String hash;
public String previousHash;
public String merkleRoot;
public String data;
public ArrayList<Transaction> transactions = new ArrayList<>();
public long timeStamp;
public int nonce; public Block(String previousHash) {
this.previousHash = previousHash;
this.timeStamp = new Date().getTime();
this.hash = calculateHash();
} public Block(String data, String previousHash) {
this.data = data;
this.previousHash = previousHash;
this.timeStamp = new Date().getTime();
this.hash = calculateHash();
} public String calculateHash() {
String calculatedhash = StringUtil.applySha256(
previousHash +
Long.toString(timeStamp) +
Integer.toString(nonce) +
merkleRoot
);
return calculatedhash;
} public void mineBlock(int difficulty) {
merkleRoot = StringUtil.getMerkleRoot(transactions);
String target = StringUtil.getDificultyString(difficulty);
while (!hash.substring(0, difficulty).equals(target)) {
nonce++;
hash = calculateHash();
}
System.out.println("Block Mined!!! : " + hash);
} public boolean addTransaction(Transaction transaction) {
if (transaction == null) return false;
if ((previousHash != "0")) {
if ((transaction.processTransaction() != true)) {
System.out.println("Transaction failed to process. Discarded.");
return false;
}
}
transactions.add(transaction);
System.out.println("Transaction Successfully added to Block");
return true;
} }
A complete test .
We've tested sending money from the wallet before , Then modify the blockchain to check its effectiveness . But first, let's create some new currencies , There are many ways to create a new currency , Take the blockchain in bitcoin as an example : A successful miner will get a reward . But here we just want to release money in the genesis block . It's like bitcoin , So we modify our main function to achieve the following purpose .
- Genesis block releases 100 A currency for walletA
- Modify the blockchain to verify the validity of the account
- Test to see if everything is running
Chain class .
import org.bouncycastle.jce.provider.BouncyCastleProvider; import java.security.Security;
import java.util.ArrayList;
import java.util.HashMap; public class Chain {
public static ArrayList<Block> blockchain = new ArrayList<>();
public static HashMap<String, TransactionOutput> UTXOs = new HashMap<>();
public static int difficulty = 3;
public static float minimumTransaction = 0.1f;
public static Wallet walletA;
public static Wallet walletB;
public static Transaction genesisTransaction; public static void main(String[] args) {
Security.addProvider(new BouncyCastleProvider());
walletA = new Wallet();
walletB = new Wallet(); Wallet coinbase = new Wallet(); genesisTransaction = new Transaction(coinbase.publicKey, walletA.publicKey, 100f, null);
genesisTransaction.generateSignature(coinbase.privateKey);
genesisTransaction.transactionId = "0";
genesisTransaction.outputs.add(new TransactionOutput(genesisTransaction.reciepient, genesisTransaction.value, genesisTransaction.transactionId));
UTXOs.put(genesisTransaction.outputs.get(0).id, genesisTransaction.outputs.get(0)); System.out.println("Creating and Mining Genesis block... ");
Block genesis = new Block("0");
genesis.addTransaction(genesisTransaction);
addBlock(genesis); //testing
Block block1 = new Block(genesis.hash);
System.out.println("\nWalletA's balance is: " + walletA.getBalance());
System.out.println("\nWalletA is Attempting to send funds (40) to WalletB...");
block1.addTransaction(walletA.sendFunds(walletB.publicKey, 40f));
addBlock(block1);
System.out.println("\nWalletA's balance is: " + walletA.getBalance());
System.out.println("WalletB's balance is: " + walletB.getBalance()); Block block2 = new Block(block1.hash);
System.out.println("\nWalletA Attempting to send more funds (1000) than it has...");
block2.addTransaction(walletA.sendFunds(walletB.publicKey, 1000f));
addBlock(block2);
System.out.println("\nWalletA's balance is: " + walletA.getBalance());
System.out.println("WalletB's balance is: " + walletB.getBalance()); Block block3 = new Block(block2.hash);
System.out.println("\nWalletB is Attempting to send funds (20) to WalletA...");
block3.addTransaction(walletB.sendFunds(walletA.publicKey, 20));
System.out.println("\nWalletA's balance is: " + walletA.getBalance());
System.out.println("WalletB's balance is: " + walletB.getBalance()); isChainValid();
} public static void addBlock(Block newBlock) {
newBlock.mineBlock(difficulty);
blockchain.add(newBlock);
} public static Boolean isChainValid() {
Block currentBlock;
Block previousBlock;
String hashTarget = new String(new char[difficulty]).replace('\0', '0');
HashMap<String, TransactionOutput> tempUTXOs = new HashMap<>();
tempUTXOs.put(genesisTransaction.outputs.get(0).id, genesisTransaction.outputs.get(0)); for (int i = 1; i < blockchain.size(); i++) { currentBlock = blockchain.get(i);
previousBlock = blockchain.get(i - 1);
if (!currentBlock.hash.equals(currentBlock.calculateHash())) {
System.out.println("#Current Hashes not equal");
return false;
}
if (!previousBlock.hash.equals(currentBlock.previousHash)) {
System.out.println("#Previous Hashes not equal");
return false;
}
if (!currentBlock.hash.substring(0, difficulty).equals(hashTarget)) {
System.out.println("#This block hasn't been mined");
return false;
} TransactionOutput tempOutput;
for (int t = 0; t < currentBlock.transactions.size(); t++) {
Transaction currentTransaction = currentBlock.transactions.get(t); if (!currentTransaction.verifySignature()) {
System.out.println("#Signature on Transaction(" + t + ") is Invalid");
return false;
}
if (currentTransaction.getInputsValue() != currentTransaction.getOutputsValue()) {
System.out.println("#Inputs are note equal to outputs on Transaction(" + t + ")");
return false;
} for (TransactionInput input : currentTransaction.inputs) {
tempOutput = tempUTXOs.get(input.transactionOutputId); if (tempOutput == null) {
System.out.println("#Referenced input on Transaction(" + t + ") is Missing");
return false;
} if (input.UTXO.value != tempOutput.value) {
System.out.println("#Referenced input Transaction(" + t + ") value is Invalid");
return false;
} tempUTXOs.remove(input.transactionOutputId);
} for (TransactionOutput output : currentTransaction.outputs) {
tempUTXOs.put(output.id, output);
} if (currentTransaction.outputs.get(0).reciepient != currentTransaction.reciepient) {
System.out.println("#Transaction(" + t + ") output reciepient is not who it should be");
return false;
}
if (currentTransaction.outputs.get(1).reciepient != currentTransaction.sender) {
System.out.println("#Transaction(" + t + ") output 'change' is not sender.");
return false;
} } }
System.out.println("Blockchain is valid");
return true;
}
}
Running results .
Now the wallet can send the amount safely in the blockchain , Only when the wallet has the amount can it be sent to others . That means you have your own cryptocurrency .
To sum up , We have implemented... In the blockchain :
- Allow all users to create wallets
- utilize ECDSA Create a public and private key for the wallet
- Through digital signature algorithm to prove ownership, so you can transfer funds safely
- Finally, all users are allowed to add transactions in the blockchain
【 primary 】 use Java Write the first blockchain ( Two ) More articles about
- 【 primary 】 use Java Write the first blockchain ( One )
The main purpose of writing this essay is to help you understand how to learn blockchain technology development . [ This article forbids any form of full text paste reprint , This article is from zacky31 The essay of ] The goal is : Create a basic " Blockchain " Implement a simple one ...
- use Java Write the first blockchain
Original address :https://www.cnblogs.com/zacky31/p/9057193.html The goal is : Create a basic “ Blockchain ” Realize a simple mining system Premise : Have a certain foundation for object-oriented programming ...
- How do I Java Transformation into Go Blockchain Engineer
How do I Java Transformation into Go Blockchain Engineer This article comes from a statement about core development of Biyuan chain Preface IT Before joining the Biyuan chain, the tribe has been doing Java Developed , I saw Go A little hesitant , I'm afraid I can't pass the interview , As a result, the consideration of mastering a language is correct ...
- use Java Implement simple blockchain
use Java Implement simple blockchain 1. summary In this paper , We will learn the basic concepts of blockchain Technology . It will also be used according to the concept Java To implement a basic application . further , We will discuss some advanced concepts and practical applications of this technology . 2. ...
- Use java Create your first blockchain ( The second part )
The purpose of this series of tutorials is to help you understand how to develop blockchain Technology . In this second tutorial , We will : Create a simple wallet : Send signed transactions using our blockchain : It feels cooler . All this will give us our own cryptocurrency ! From the last tutorial ...
- Use java Create your first blockchain ( The first part )
The purpose of this series of tutorials is to help you understand how to develop blockchain Technology . In this tutorial , We will : Create your first ( very ) Basic “ Blockchain ”. The implementation of simple work proves ( mining ) System . Marvel at the possibility . ( I assume you have a basic understanding of object-oriented programming ...
- [C#] Use C# Write your own blockchain mining algorithm
[C#] Use C# Write your own mining algorithm for blockchain The original article comes from :Code your own blockchain mining algorithm in Go! , The original article passed Go Language to achieve , here ...
- be based on java Simple blockchain implemented
technology :maven3.0.5 + jdk1.8 summary Blockchain is distributed data storage . Point to point transmission . Consensus mechanism . New application mode of computer technology such as encryption algorithm . The so-called consensus mechanism is to build trust among different nodes in the blockchain system . To acquire the rights and interests of ...
- android and java Ethereum develops blockchain applications using web3j Class library
How to use web3j by Java Application or Android App Add Ethereum blockchain support , The content of the course involves the core concepts of Ethereum , For example, account management includes account creation . Wallet creation . Transaction transfer , Trade and status . Smart contract development and interaction . Filters and ...
Random recommendation
- iOS socket note
ios The end of the service : download AsyncSocket Development framework , Drag into the project // establish #import "ViewController.h" #import <sys/socket. ...
- thinkphp in page Method
page Method is also one of the coherent operation methods of the model , It is a personalized operation method that is completely for paging query . usage We have learned about limit Method for paging queries , and page Method is a more user-friendly way of paging query , example ...
- File wall CFilewall
File wall CFilewall Recorded in 2013-09-26 == @[ Code ] [C#] []WPF] #### Using some company components and amplification , But not much , It can be extracted separately --- Program structure - Control ...
- Wang Xuechang's AAA Trees
Let's respond to Wang Xuechang's call and bravely write separately splay and lct Well ! It's good to write the Dafa separately !!!!!!!!!!! Du Jiao's ch[4] Is too weak !!!! #include <stdio.h> #include < ...
- C++ Builder Multi thread programming technology experience ( turn )
Source :C++ Builder Multi thread programming technology experience The feasibility of threads In many cases , You may need to create threads for your program . Here are some of the possibilities : (1) If you are creating a multi document interface (Multiple Document ...
- pandas.DataFrame Of pivot() and unstack() Realize row to column conversion
Example : The following table needs to be converted into columns : The code is as follows : # -*- coding:utf-8 -*- import pandas as pd import MySQLdb from warnings impor ...
- webdriver Save captcha screenshot
element = wait.until ( EC.visibility_of_element_located((By.CSS_SELECTOR,'.quc-main .quc-field-captc ...
- spring In a container, a bean Depend on another bean Need to pass through ref The way to inject it By constructor or property
spring In a container, a bean Depend on another bean Need to pass through ref The way to inject it By constructor or property
- It is worth collecting : A very complete MySQL standard
One . Database command specification All database object names must be lowercase and separated with an underscore . All database object names are disabled MySQL Reserved keyword ( If the table name contains a keyword query , You need to put it in single quotes ). The naming of database objects should be able to ...
- stay myeclipse Publish your own webservice
What is? WebServices? It's a universal model for building applications , It can run in any operating system supporting network communication ; It's a new kind of web Application branches , It's self-contained . Since the description . Modular applications , You can publish . location . adopt w ...