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

  1. 【 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 ...

  2. 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 ...

  3. 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 ...

  4. 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. ...

  5. 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 ...

  6. 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 ...

  7. [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 ...

  8. 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 ...

  9. 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

  1. iOS socket note

    ios The end of the service : download  AsyncSocket Development framework , Drag into the project // establish #import "ViewController.h" #import <sys/socket. ...

  2. 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 ...

  3. 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 ...

  4. 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 < ...

  5. 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 ...

  6. 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 ...

  7. webdriver Save captcha screenshot

    element = wait.until ( EC.visibility_of_element_located((By.CSS_SELECTOR,'.quc-main .quc-field-captc ...

  8. 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

  9. 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 ...

  10. 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 ...