Commit 870ce94b authored by Michel Schudel's avatar Michel Schudel

fixed some bugs.

parent 348350ab
......@@ -16,7 +16,7 @@ import { PeersComponent } from './peers/peers.component';
import { PeersService } from './peers/peers.service';
const routes: Routes = [
{ path: '', redirectTo: '/transactions/pending', pathMatch: 'full' },
{ path: '', redirectTo: '/transactions', pathMatch: 'full' },
{ path: 'transactions', component: PendingTransactionsComponent },
{ path: 'transactions/create', component: CreateTransactionComponent },
{ path: 'blockchain', component: BlockchainComponent },
......
package nl.craftsmen.blockchain.craftsmencoinnode;
import nl.craftsmen.blockchain.craftsmencoinnode.blockchain.Block;
import nl.craftsmen.blockchain.craftsmencoinnode.blockchain.BlockChain;
import nl.craftsmen.blockchain.craftsmencoinnode.blockchain.BlockchainManager;
import nl.craftsmen.blockchain.craftsmencoinnode.network.Network;
import nl.craftsmen.blockchain.craftsmencoinnode.transaction.Transaction;
import nl.craftsmen.blockchain.craftsmencoinnode.wallet.WalletDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
......@@ -77,7 +83,7 @@ public class CraftsCoinRestController {
* @param peer the peer that initiated the request.
* @param block the new block.
*/
@PostMapping("api/newblock")
@PostMapping("/api/newblock")
public void newBlock(@RequestHeader(value = "peer", required = false) String peer, @RequestBody Block block) {
blockchainManager.newBlockReceived(block, peer);
}
......
package nl.craftsmen.blockchain.craftsmencoinnode;
package nl.craftsmen.blockchain.craftsmencoinnode.blockchain;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import nl.craftsmen.blockchain.craftsmencoinnode.transaction.Transaction;
import java.util.HashSet;
import java.util.Set;
......@@ -18,7 +19,7 @@ public class Block {
public Block() {
}
public Block(long index, long timestamp, Set<Transaction> transactions, long proof, String previousHash) {
Block(long index, long timestamp, Set<Transaction> transactions, long proof, String previousHash) {
this.index = index;
this.timestamp = timestamp;
this.transactions = new HashSet<>(transactions);
......
package nl.craftsmen.blockchain.craftsmencoinnode;
package nl.craftsmen.blockchain.craftsmencoinnode.blockchain;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import nl.craftsmen.blockchain.craftsmencoinnode.transaction.Transaction;
import java.time.Instant;
import java.util.ArrayList;
......@@ -42,7 +43,8 @@ public class BlockChain {
public long getIndexOfNextBlock() {
return getIndexOfLastBlock() + 1;
}
public long getIndexOfLastBlock() {
private long getIndexOfLastBlock() {
Block block = getLastBlock();
return block != null ? block.getIndex() : -1;
}
......@@ -91,16 +93,7 @@ public class BlockChain {
public boolean isNewBlockValid(Block newBlock) {
Block lastBlock = getLastBlock();
if (!newBlock.getPreviousHash().equals(HashUtil.hash(lastBlock))) {
return false;
}
if (!validProof(lastBlock.getProof(), newBlock.getProof())) {
return false;
}
return true;
return newBlock.getPreviousHash().equals(HashUtil.hash(lastBlock)) && validProof(lastBlock.getProof(), newBlock.getProof());
}
public long proofOfWork() {
......
package nl.craftsmen.blockchain.craftsmencoinnode;
package nl.craftsmen.blockchain.craftsmencoinnode.blockchain;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import nl.craftsmen.blockchain.craftsmencoinnode.util.InstanceInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -11,7 +12,7 @@ import java.io.File;
import java.io.IOException;
@Component
public final class BlockChainRepository {
final class BlockChainRepository {
private InstanceInfo instanceInfo;
......@@ -19,11 +20,11 @@ public final class BlockChainRepository {
private static final Logger LOGGER = LoggerFactory.getLogger(BlockChainRepository.class);
@Autowired
public BlockChainRepository(InstanceInfo instanceInfo) {
BlockChainRepository(InstanceInfo instanceInfo) {
this.instanceInfo = instanceInfo;
}
public BlockChain loadBlockChain() {
BlockChain loadBlockChain() {
try {
File file = createBlockchainFileForThisNode();
LOGGER.info("trying to load blockchain for this node under filename {}", file.getName());
......@@ -41,7 +42,7 @@ public final class BlockChainRepository {
}
}
public void saveBlockChain(BlockChain blockChain) {
void saveBlockChain(BlockChain blockChain) {
try {
File file = createBlockchainFileForThisNode();
ObjectMapper objectMapper = new ObjectMapper();
......
package nl.craftsmen.blockchain.craftsmencoinnode;
package nl.craftsmen.blockchain.craftsmencoinnode.blockchain;
import nl.craftsmen.blockchain.craftsmencoinnode.transaction.Transaction;
import nl.craftsmen.blockchain.craftsmencoinnode.transaction.TransactionPool;
import nl.craftsmen.blockchain.craftsmencoinnode.wallet.WalletDto;
import nl.craftsmen.blockchain.craftsmencoinnode.network.Network;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -58,7 +62,10 @@ public class BlockchainManager {
}
public long newTransaction(Transaction transaction, String sourcePeer) {
LOGGER.info("received transaction: {}", transaction);
LOGGER.info("received transaction: {} from source peer {}", transaction, sourcePeer);
if (transaction.getId() == null) {
transaction = new Transaction(transaction.getFrom(), transaction.getTo(), transaction.getAmount());
}
if (!transactionPool.getCurrentTransactions().contains(transaction)) {
LOGGER.info("transaction {} is new, adding it to the list of pending transactions.", transaction);
transactionPool.addTransaction(transaction);
......@@ -87,7 +94,7 @@ public class BlockchainManager {
public void reachConsensus() {
private void reachConsensus() {
List<BlockChain> otherChains = network.retrieveBlockchainsFromPeers();
LOGGER.info("blockchains from peers received. Checking...");
for (BlockChain otherChain : otherChains) {
......
package nl.craftsmen.blockchain.craftsmencoinnode;
package nl.craftsmen.blockchain.craftsmencoinnode.blockchain;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
......@@ -7,9 +7,9 @@ import org.apache.commons.codec.binary.Hex;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class HashUtil {
class HashUtil {
public static String hash(Block block) {
static String hash(Block block) {
try {
ObjectMapper mapper = new ObjectMapper();
String blockString = mapper.writeValueAsString(block);
......@@ -21,7 +21,7 @@ public class HashUtil {
}
public static String createHash(String aString) {
static String createHash(String aString) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(aString.getBytes());
......
package nl.craftsmen.blockchain.craftsmencoinnode;
package nl.craftsmen.blockchain.craftsmencoinnode.network;
import nl.craftsmen.blockchain.craftsmencoinnode.blockchain.Block;
import nl.craftsmen.blockchain.craftsmencoinnode.blockchain.BlockChain;
import nl.craftsmen.blockchain.craftsmencoinnode.transaction.Transaction;
import nl.craftsmen.blockchain.craftsmencoinnode.util.InstanceInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.ResourceAccessException;
......@@ -14,7 +20,10 @@ import org.springframework.web.client.RestTemplate;
import javax.annotation.PostConstruct;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Component
......@@ -49,12 +58,13 @@ public class Network {
peers = peersRepository.loadPeers();
}
public void notifyPeersOfNewTransaction(Transaction transaction, String sourePeer) {
Set<String> collect = peers.stream().filter(p -> !p.equals(sourePeer)).collect(Collectors.toSet());
public void notifyPeersOfNewTransaction(Transaction transaction, String sourcePeer) {
Set<String> collect = peers.stream().filter(p -> !p.equals(sourcePeer)).collect(Collectors.toSet());
LOGGER.info("notifying the following peers of transaction {}: {}", transaction, collect);
for (String node : collect) {
HttpEntity<Transaction> entity = new HttpEntity<>(transaction, createHttpHeaders());
post(node, "/newtransaction", entity, Object.class);
post(node, "/newtransaction", entity, new ParameterizedTypeReference<Object>() {
});
}
}
......@@ -64,7 +74,7 @@ public class Network {
LOGGER.info("notifying the following peers of new block {}: {}", newBlock, collect);
for (String node : peers.stream().filter(p -> !p.equals(sourcePeer)).collect(Collectors.toSet())) {
HttpEntity<Block> entity = new HttpEntity<>(newBlock, createHttpHeaders());
post(node, "newblock", entity, null);
post(node, "/newblock", entity, new ParameterizedTypeReference<Object>() {});
}
}
......@@ -89,7 +99,8 @@ public class Network {
} else {
LOGGER.info("registering this node to peers {}", peers);
for (String peer : peers) {
ResponseEntity<Set> listResponseEntity = post(peer, "/registernode", instanceInfo.getNode(), Set.class);
ResponseEntity<Set<String>> listResponseEntity = post(peer, "/registernode", instanceInfo.getNode(), new ParameterizedTypeReference<Set<String>>() {
});
if (listResponseEntity != null) {
Set<String> list = listResponseEntity.getBody();
LOGGER.info("remote peer {} returned peer list: {}", peer, list);
......@@ -106,7 +117,8 @@ public class Network {
LOGGER.info("peer {} is not previously known to this node. Peer registration will be forwarded to known peer: {}", newPeer, peers);
peers.add(newPeer);
for (String node : peers.stream().filter(p -> !p.equals(newPeer)).collect(Collectors.toSet())) {
ResponseEntity<Set> listResponseEntity = post(node, "/registernode", newPeer, Set.class);
ResponseEntity<Set<String>> listResponseEntity = post(node, "/registernode", newPeer, new ParameterizedTypeReference<Set<String>>() {
});
if (listResponseEntity != null) {
Set<String> list = listResponseEntity.getBody();
peers.addAll(list.stream().filter(e -> !e.equals(instanceInfo.getNode())).collect(Collectors.toSet()));
......@@ -138,10 +150,17 @@ public class Network {
}
private <T> ResponseEntity<T> post(String peer, String action, Object object, Class<T> clazz) {
private <T> ResponseEntity<T> post(String peer, String action, Object object, ParameterizedTypeReference<T> typeRef) {
try {
ResponseEntity<T> response = restTemplate.postForEntity("http://" + peer + "/api" + action, object, clazz, (Object) null);
return response;
HttpEntity<?> httpEntity;
if (object instanceof HttpEntity) {
httpEntity = (HttpEntity)object;
} else {
httpEntity = new HttpEntity<>(object);
}
return restTemplate.exchange("http://" + peer + "/api" + action, HttpMethod.POST, httpEntity, typeRef);
//return restTemplate.postForEntity("http://" + peer + "/api" + action, object, clazz, (Object) null);
} catch (ResourceAccessException e) {
LOGGER.warn("peer {} not found, removing from peer list.", peer);
peers.remove(peer);
......@@ -150,12 +169,14 @@ public class Network {
return null;
}
private String createHostEndpoint() {
return this.bootstrapPeerHost + ":" + bootstrapPeerPort;
}
private void registerThroughBootstrapNode() {
ResponseEntity<Set> listResponseEntity = post(createHostEndpoint(), "/registernode", instanceInfo.getNode(), Set.class);
ResponseEntity<Set<String>> listResponseEntity = post(createHostEndpoint(), "/registernode", instanceInfo.getNode(), new ParameterizedTypeReference<Set<String>>() {
});
if (listResponseEntity != null) {
Set<String> list = listResponseEntity.getBody();
LOGGER.info("received peer list: {}", list);
......
package nl.craftsmen.blockchain.craftsmencoinnode;
package nl.craftsmen.blockchain.craftsmencoinnode.network;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import nl.craftsmen.blockchain.craftsmencoinnode.util.InstanceInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -13,7 +15,7 @@ import java.util.HashSet;
import java.util.Set;
@Component
public final class PeersRepository {
final class PeersRepository {
private InstanceInfo instanceInfo;
......@@ -21,18 +23,21 @@ public final class PeersRepository {
private static final Logger LOGGER = LoggerFactory.getLogger(PeersRepository.class);
@Autowired
public PeersRepository(InstanceInfo instanceInfo) {
PeersRepository(InstanceInfo instanceInfo) {
this.instanceInfo = instanceInfo;
}
public Set<String> loadPeers() {
Set<String> loadPeers() {
try {
File file = createPeersFileForThisNode();
LOGGER.info("trying to load peers for this node under filename {}", file.getName());
if (file.exists()) {
LOGGER.info("existing peers file found, loading...");
ObjectMapper objectMapper = new ObjectMapper();
Set<String> peers = objectMapper.readValue(file, Set.class);
TypeReference<Set<String>> typeRef
= new TypeReference<Set<String>>() {
};
Set<String> peers = objectMapper.readValue(file, typeRef);
LOGGER.info("peers succesfully loaded!");
return peers;
} else {
......@@ -43,7 +48,7 @@ public final class PeersRepository {
}
}
public void savePeers(Set<String> peers) {
void savePeers(Set<String> peers) {
try {
File file = createPeersFileForThisNode();
ObjectMapper objectMapper = new ObjectMapper();
......
package nl.craftsmen.blockchain.craftsmencoinnode;
package nl.craftsmen.blockchain.craftsmencoinnode.transaction;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal;
import java.util.UUID;
......@@ -26,6 +27,7 @@ public class Transaction {
}
@JsonProperty()
public UUID getId() {
return id;
}
......
package nl.craftsmen.blockchain.craftsmencoinnode;
package nl.craftsmen.blockchain.craftsmencoinnode.transaction;
import nl.craftsmen.blockchain.craftsmencoinnode.blockchain.BlockchainManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
......
package nl.craftsmen.blockchain.craftsmencoinnode;
package nl.craftsmen.blockchain.craftsmencoinnode.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -16,10 +16,8 @@ public class InstanceInfo {
private static final Logger LOGGER = LoggerFactory.getLogger(InstanceInfo.class);
private ServerProperties serverProperties;
private String host;
private int port;
private String node;
private String hostnameNode;
@Autowired
public InstanceInfo(ServerProperties serverProperties) {
......@@ -32,11 +30,8 @@ public class InstanceInfo {
String host = Inet4Address
.getLocalHost()
.getHostAddress();
String hostName = Inet4Address
.getLocalHost().getHostName();
this.port = serverProperties.getPort();
this.node = host + ":" + serverProperties.getPort();
this.hostnameNode = hostName + ":" + serverProperties.getPort();
LOGGER.info("node name of this node is {}", node);
} catch (UnknownHostException e) {
throw new RuntimeException(e);
......@@ -53,9 +48,6 @@ public class InstanceInfo {
return node;
}
public String getHostnameNode() {
return hostnameNode;
}
public int getPort() {
return port;
......
package nl.craftsmen.blockchain.craftsmencoinnode;
package nl.craftsmen.blockchain.craftsmencoinnode.wallet;
import nl.craftsmen.blockchain.craftsmencoinnode.transaction.Transaction;
import java.math.BigDecimal;
import java.util.List;
public class WalletDto {
private BigDecimal balance;
......
package nl.craftsmen.blockchain.craftsmencoinnode;
import nl.craftsmen.blockchain.craftsmencoinnode.util.InstanceInfo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment