Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added check on veichle identification number uniqueness #4

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions src/main/java/io/horizen/lambo/CarRegistryApplicationState.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
import scala.util.Try;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import scala.collection.JavaConverters;

public class CarRegistryApplicationState implements ApplicationState {

Expand All @@ -29,16 +30,29 @@ public CarRegistryApplicationState(CarInfoDBService carInfoDbService) {

@Override
public boolean validate(SidechainStateReader stateReader, SidechainBlock block) {
return true;
}
//We check that there are no multiple transactions declaring the same VIN inside the block
Set<String> vinList = new HashSet<>();
for (BoxTransaction<Proposition, Box<Proposition>> t : JavaConverters.seqAsJavaList(block.transactions())){
if (t instanceof CarDeclarationTransaction){
for (String currentVin : carInfoDbService.extractVinFromBoxes(t.newBoxes())){
if (vinList.contains(currentVin)){
return false;
}else{
vinList.add(currentVin);
}
}
}
}
return true;
}

@Override
public boolean validate(SidechainStateReader stateReader, BoxTransaction<Proposition, Box<Proposition>> transaction) {
// we go though all CarDeclarationTransactions and verify that each CarBox reflects to unique Car.
if (CarDeclarationTransaction.class.isAssignableFrom(transaction.getClass())){
if (transaction instanceof CarDeclarationTransaction){
Set<String> vinList = carInfoDbService.extractVinFromBoxes(transaction.newBoxes());
for (String vin : vinList) {
if (! carInfoDbService.validateVin(vin, null)){
if (! carInfoDbService.validateVin(vin, Optional.empty())){
return false;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/io/horizen/lambo/car/api/CarApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ private ApiResponse createCar(SidechainNodeView view, CreateCarBoxRequest ent) {
.parseBytes(BytesUtils.fromHexString(ent.proposition));

//check that the vin is unique (both in local veichle store and in mempool)
if (! carInfoDBService.validateVin(ent.vin, view.getNodeMemoryPool())){
if (! carInfoDBService.validateVin(ent.vin, Optional.of(view.getNodeMemoryPool()))){
throw new IllegalStateException("Vehicle identification number already present in blockchain");
}

Expand Down
21 changes: 8 additions & 13 deletions src/main/java/io/horizen/lambo/car/services/CarInfoDBService.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,8 @@
import io.horizen.lambo.car.box.CarSellOrderBox;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.ByteBuffer;
import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.util.ArrayList;
import scorex.crypto.hash.Blake2b256;
import java.util.*;

/**
* This service manages a local db with the list of all veichle identification numbers (vin) declared on the chain.
Expand Down Expand Up @@ -57,13 +53,13 @@ public void updateVin(byte[] version, Set<String> vinToAdd, Set<String> vinToRe
* @param memoryPool if not null, the vin is checked also against the mempool transactions
* @return true if the vin is valid (not already declared)
*/
public boolean validateVin(String vin, NodeMemoryPool memoryPool){
public boolean validateVin(String vin, Optional<NodeMemoryPool> memoryPool){
if (carInfoStorage.get(buildDBElement(vin).getKey()).isPresent()){
return false;
}
//in the vin is not found, and the mempool was provided, we check also there
if (memoryPool != null) {
for (BoxTransaction<Proposition, Box<Proposition>> transaction : memoryPool.getTransactions()) {
if (memoryPool.isPresent()) {
for (BoxTransaction<Proposition, Box<Proposition>> transaction : memoryPool.get().getTransactions()) {
Set<String> vinInMempool = extractVinFromBoxes(transaction.newBoxes());
if (vinInMempool.contains(vin)){
return false;
Expand Down Expand Up @@ -99,10 +95,9 @@ public Set<String> extractVinFromBoxes(List<Box<Proposition>> boxes){


private Pair<ByteArrayWrapper, ByteArrayWrapper> buildDBElement(String vin){
//we use a fixed key size of 32, which is the default of iohk.iodb used as underline storage
ByteBuffer keyBuffer = ByteBuffer.allocate(32).put(vin.getBytes());
ByteArrayWrapper keyWrapper = new ByteArrayWrapper(keyBuffer.array());
//the value is not important (we need just a key set, each key is a vin)
//we hash the vin to be sure the key has a fixed size of 32, which is the default of iohk.iodb used as underline storage
ByteArrayWrapper keyWrapper = new ByteArrayWrapper(Blake2b256.hash(vin));
//the value is not important (we need just a key set, each key is a vin hash)
ByteArrayWrapper valueWrapper = new ByteArrayWrapper(new byte[1]);
return new Pair<>(keyWrapper, valueWrapper);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@
// As outputs it contains possible RegularBoxes(to pay fee and change) and new CarBox entry.
// No specific unlockers to parent class logic, but has specific new box.
// TODO: add specific mempool incompatibility checker to deprecate keeping in the Mempool txs that declare the same Car.
public final class CarDeclarationTransaction extends AbstractRegularTransaction {
public final class CarDeclarationTransaction<P extends Proposition, B extends NoncedBox<P>> extends AbstractRegularTransaction {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that it's correct to define generics here, because in one of the parent classes the proper values were already set to the templates. The previous error with instanceof occurs because of the generics, which are not covariant.
I would suggest to revert current line changes and in the error place use stuff like CarDeclarationTransaction.class.isInstance(t).
Should be fine.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!


private final CarBoxData outputCarBoxData;

private List<NoncedBox<Proposition>> newBoxes;

public CarDeclarationTransaction(List<byte[]> inputRegularBoxIds,
Expand Down