Created
December 4, 2018 13:36
-
-
Save samanshahmohamadi/256f40b618b77f2d5a89dbcf27ef8585 to your computer and use it in GitHub Desktop.
Iroha WebApplication
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.avalblock.irohaweb.controller; | |
import com.avalblock.common.exception.BaseException; | |
import com.avalblock.irohaweb.service.interfaces.IIrohaService; | |
import com.google.protobuf.ByteString; | |
import com.google.protobuf.Descriptors; | |
import com.google.protobuf.InvalidProtocolBufferException; | |
import io.grpc.ManagedChannel; | |
import io.grpc.ManagedChannelBuilder; | |
import io.swagger.annotations.ApiOperation; | |
import iroha.protocol.*; | |
import jp.co.soramitsu.iroha.*; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.http.HttpStatus; | |
import org.springframework.http.ResponseEntity; | |
import org.springframework.web.bind.annotation.*; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.validation.Valid; | |
import java.io.IOException; | |
import java.math.BigInteger; | |
import java.nio.file.Files; | |
import java.nio.file.Paths; | |
@RestController | |
public class IrohaController { | |
@Autowired | |
IIrohaService irohaService; | |
static { | |
try { | |
System.loadLibrary("irohajava"); | |
} catch (UnsatisfiedLinkError e) { | |
System.err.println("Native code library failed to load. \n" + e); | |
System.exit(1); | |
} | |
} | |
private static ModelCrypto crypto = new ModelCrypto(); | |
private static ModelTransactionBuilder txBuilder = new ModelTransactionBuilder(); | |
private static ModelQueryBuilder queryBuilder = new ModelQueryBuilder(); | |
public static byte[] toByteArray(ByteVector blob) { | |
byte bs[] = new byte[(int)blob.size()]; | |
for (int i = 0; i < blob.size(); ++i) { | |
bs[i] = (byte)blob.get(i); | |
} | |
return bs; | |
} | |
public static String readKeyFromFile(String path) { | |
try { | |
return new String(Files.readAllBytes(Paths.get(path))); | |
} catch (IOException e) { | |
System.err.println("Unable to read key files.\n " + e); | |
System.exit(1); | |
} | |
return ""; | |
} | |
@RequestMapping(method = RequestMethod.POST, value = "/create/account") | |
public ResponseEntity createAccount(@RequestParam String accountName, @RequestParam String domainName ) throws BaseException, IOException { | |
// String txHash = irohaService.createAccount("admin@test", accountName, domainName); | |
Keypair keys = crypto.convertFromExisting(readKeyFromFile("./artifacts/[email protected]"), | |
readKeyFromFile("./artifacts/[email protected]")); | |
long currentTime = System.currentTimeMillis(); | |
String creator = "admin@test"; | |
long startQueryCounter = 1; | |
// build transaction (still unsigned) | |
UnsignedTx utx = txBuilder.creatorAccountId(creator) | |
.createdTime(BigInteger.valueOf(currentTime)) | |
.createDomain("ru", "user") | |
.createAsset("dollar", "ru", (short)2).build(); | |
// sign transaction and get its binary representation (Blob) | |
ByteVector txblob = new ModelProtoTransaction(utx).signAndAddSignature(keys).finish().blob(); | |
// Convert ByteVector to byte array | |
byte bs[] = toByteArray(txblob); | |
// create proto object | |
TransactionOuterClass.Transaction protoTx = null; | |
try { | |
protoTx = TransactionOuterClass.Transaction.parseFrom(bs); | |
} catch (InvalidProtocolBufferException e) { | |
System.err.println("Exception while converting byte array to protobuf:" + e.getMessage()); | |
System.exit(1); | |
} | |
// Send transaction to iroha | |
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50051).usePlaintext(true).build(); | |
CommandServiceGrpc.CommandServiceBlockingStub stub = CommandServiceGrpc.newBlockingStub(channel); | |
stub.torii(protoTx); | |
// wait to ensure transaction was processed | |
try { | |
Thread.sleep(5000); | |
} | |
catch(InterruptedException ex) { | |
Thread.currentThread().interrupt(); | |
} | |
// create status request | |
System.out.println("Hash of the transaction: " + utx.hash().hex()); | |
ByteVector txhash = utx.hash().blob(); | |
byte bshash[] = toByteArray(txhash); | |
Endpoint.TxStatusRequest request = Endpoint.TxStatusRequest.newBuilder().setTxHash(ByteString.copyFrom(bshash)).build(); | |
Endpoint.ToriiResponse response = stub.status(request); | |
String status = response.getTxStatus().name(); | |
System.out.println("Status of the transaction is: " + status); | |
if (!status.equals("COMMITTED")) { | |
System.err.println("Your transaction wasn't committed"); | |
// System.exit(1); | |
} | |
// query result of transaction we've just sent | |
UnsignedQuery uquery = queryBuilder.creatorAccountId(creator) | |
.queryCounter(BigInteger.valueOf(startQueryCounter)) | |
.createdTime(BigInteger.valueOf(currentTime)) | |
.getAssetInfo("dollar#ru") | |
.build(); | |
ByteVector queryBlob = new ModelProtoQuery(uquery).signAndAddSignature(keys).finish().blob(); | |
byte bquery[] = toByteArray(queryBlob); | |
Queries.Query protoQuery = null; | |
try { | |
protoQuery = Queries.Query.parseFrom(bquery); | |
} catch (InvalidProtocolBufferException e) { | |
System.err.println("Exception while converting byte array to protobuf:" + e.getMessage()); | |
System.exit(1); | |
} | |
QueryServiceGrpc.QueryServiceBlockingStub queryStub = QueryServiceGrpc.newBlockingStub(channel); | |
QryResponses.QueryResponse queryResponse = queryStub.find(protoQuery); | |
Descriptors.FieldDescriptor fieldDescriptor = queryResponse.getDescriptorForType().findFieldByName("asset_response"); | |
if (!queryResponse.hasField(fieldDescriptor)) { | |
System.err.println("Query response error"); | |
// System.exit(1); | |
} else { | |
System.out.println("Query responsed with asset response"); | |
} | |
QryResponses.Asset asset = queryResponse.getAssetResponse().getAsset(); | |
System.out.println("Asset Id = " + asset.getAssetId()); | |
System.out.println("Precision = " + asset.getPrecision()); | |
System.out.println("done!"); | |
return new ResponseEntity<>(utx.hash().toString(), HttpStatus.OK); | |
} | |
@RequestMapping(method = RequestMethod.POST, value = "/create/asset") | |
public ResponseEntity createAccount(@RequestParam String assetName, @RequestParam String domainName, @RequestParam double precision ) throws BaseException, IOException { | |
String txHash = irohaService.createAsset("admin@test", assetName, domainName, precision); | |
return new ResponseEntity<>(txHash, HttpStatus.OK); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.avalblock.irohaweb.service; | |
import com.avalblock.common.exception.ErrorCodes; | |
import com.avalblock.common.exception.InternalServerException; | |
import com.avalblock.common.exception.NotFoundException; | |
import com.avalblock.irohaweb.service.interfaces.IIrohaService; | |
import com.google.protobuf.Descriptors; | |
import iroha.protocol.*; | |
import org.apache.commons.io.FileUtils; | |
import org.springframework.stereotype.Service; | |
import java.io.File; | |
import java.io.IOException; | |
import java.math.BigInteger; | |
import java.nio.file.Files; | |
import java.nio.file.Paths; | |
import java.util.HashMap; | |
import java.util.List; | |
import iroha.protocol.Queries.Query; | |
import iroha.protocol.Queries.GetAssetInfo; | |
import iroha.protocol.QueryServiceGrpc.QueryServiceBlockingStub; | |
import iroha.protocol.CommandServiceGrpc.CommandServiceBlockingStub; | |
import iroha.protocol.Endpoint.TxStatus; | |
import iroha.protocol.Endpoint.TxStatusRequest; | |
import iroha.protocol.Endpoint.ToriiResponse; | |
import iroha.protocol.QryResponses.QueryResponse; | |
import iroha.protocol.QryResponses.AssetResponse; | |
import iroha.protocol.QryResponses.Asset; | |
import com.google.protobuf.InvalidProtocolBufferException; | |
import io.grpc.ManagedChannel; | |
import io.grpc.ManagedChannelBuilder; | |
import com.google.protobuf.ByteString; | |
import com.google.protobuf.Descriptors.FieldDescriptor; | |
import java.nio.file.Paths; | |
import java.nio.file.Files; | |
import java.io.IOException; | |
import java.math.BigInteger; | |
import java.lang.Thread; | |
import jp.co.soramitsu.iroha.*; | |
@Service | |
public class IrohaService { | |
static { | |
try { | |
System.loadLibrary("irohajava"); | |
} catch (UnsatisfiedLinkError e) { | |
System.err.println("Native code library failed to load. \n" + e); | |
System.exit(1); | |
} | |
} | |
private ModelCrypto crypto = new ModelCrypto(); | |
private ModelTransactionBuilder txBuilder = new ModelTransactionBuilder(); | |
private ModelQueryBuilder queryBuilder = new ModelQueryBuilder(); | |
private BigInteger startQueryCounter = BigInteger.valueOf(1); | |
private static byte[] toByteArray(ByteVector blob) { | |
byte bs[] = new byte[(int) blob.size()]; | |
for (int i = 0; i < blob.size(); ++i) { | |
bs[i] = (byte) blob.get(i); | |
} | |
return bs; | |
} | |
private static String readKeyFromFile(String path) throws NotFoundException { | |
try { | |
return new String(Files.readAllBytes(Paths.get(path))); | |
} catch (IOException e) { | |
System.err.println("Unable to read key files.\n " + e); | |
throw new NotFoundException(ErrorCodes.USER_NOT_FOUND); | |
} | |
} | |
private String getKey(String accountId, String keyType) throws NotFoundException { | |
return readKeyFromFile("./artifacts/" + accountId + "." + keyType); | |
} | |
private void setPubKey(String accountId, PublicKey publicKey) throws IOException { | |
writeKeyToFile(publicKey.hex(), "./artifacts/" + accountId + ".pub"); | |
} | |
private void setPrivKey(String accountId, PrivateKey privateKey) throws IOException { | |
writeKeyToFile(privateKey.hex(), "./artifacts/" + accountId + ".priv"); | |
} | |
private void writeKeyToFile(String key, String fileName) throws IOException { | |
FileUtils.writeStringToFile(new File(fileName), key, "utf-8"); | |
} | |
private String sendTransaction(String accountId, UnsignedTx utx) throws InternalServerException, NotFoundException { | |
Keypair keys = crypto.convertFromExisting(getKey(accountId, "pub"), | |
getKey(accountId, "priv")); | |
// sign transaction and get its binary representation (Blob) | |
ByteVector txblob = new ModelProtoTransaction(utx).signAndAddSignature(keys).finish().blob(); | |
// Convert ByteVector to byte array | |
byte bs[] = toByteArray(txblob); | |
// create proto object | |
TransactionOuterClass.Transaction protoTx = null; | |
try { | |
protoTx = TransactionOuterClass.Transaction.parseFrom(bs); | |
} catch (InvalidProtocolBufferException e) { | |
System.err.println("Exception while converting byte array to protobuf:" + e.getMessage()); | |
System.exit(1); | |
} | |
// Send transaction to iroha | |
ManagedChannel channel = ManagedChannelBuilder.forAddress("0.0.0.0", 50051).usePlaintext(true).build(); | |
CommandServiceGrpc.CommandServiceBlockingStub stub = CommandServiceGrpc.newBlockingStub(channel); | |
stub.torii(protoTx); | |
// wait to ensure transaction was processed | |
try { | |
Thread.sleep(5000); | |
} | |
catch(InterruptedException ex) { | |
Thread.currentThread().interrupt(); | |
} | |
// create status request | |
System.out.println("Hash of the transaction: " + utx.hash().hex()); | |
ByteVector txhash = utx.hash().blob(); | |
byte bshash[] = toByteArray(txhash); | |
Endpoint.TxStatusRequest request = Endpoint.TxStatusRequest.newBuilder().setTxHash(ByteString.copyFrom(bshash)).build(); | |
Endpoint.ToriiResponse response = stub.status(request); | |
String status = response.getTxStatus().name(); | |
System.out.println("Status of the transaction is: " + status); | |
if (!status.equals("COMMITTED")) { | |
System.err.println("Your transaction wasn't committed"); | |
throw new InternalServerException(ErrorCodes.INTERNAL_SERVER_ERROR); | |
} | |
return utx.hash().hex(); | |
} | |
private QryResponses.QueryResponse sendQuery(UnsignedQuery uquery, String creator) throws NotFoundException, InternalServerException { | |
String pubKeyStr = getKey(creator, "pub"); | |
String prvKeyStr = getKey(creator, "priv"); | |
Keypair keyPair = crypto.convertFromExisting(pubKeyStr, prvKeyStr); | |
// Send query to iroha | |
ManagedChannel channel = ManagedChannelBuilder.forAddress("0.0.0.0", 50051).usePlaintext(true).build(); | |
ByteVector queryBlob = new ModelProtoQuery(uquery).signAndAddSignature(keyPair).finish().blob(); | |
byte bquery[] = toByteArray(queryBlob); | |
Queries.Query protoQuery = null; | |
try { | |
protoQuery = Queries.Query.parseFrom(bquery); | |
} catch (InvalidProtocolBufferException e) { | |
System.err.println("Exception while converting byte array to protobuf:" + e.getMessage()); | |
System.exit(1); | |
} | |
QueryServiceGrpc.QueryServiceBlockingStub queryStub = QueryServiceGrpc.newBlockingStub(channel); | |
QryResponses.QueryResponse queryResponse = queryStub.find(protoQuery); | |
Descriptors.FieldDescriptor fieldDescriptor = queryResponse.getDescriptorForType().findFieldByName("asset_response"); | |
if (!queryResponse.hasField(fieldDescriptor)) { | |
System.err.println("Query response error"); | |
throw new InternalServerException(ErrorCodes.INTERNAL_SERVER_ERROR); | |
} else { | |
System.out.println("Query responsed successfully"); | |
} | |
return queryResponse; | |
} | |
public String addAssetQty(String assetId, String creator, double amount) throws NotFoundException, InternalServerException { | |
UnsignedTx utx = txBuilder.creatorAccountId(creator) | |
.createdTime(BigInteger.valueOf(System.currentTimeMillis())) | |
.addAssetQuantity(assetId, String.valueOf(amount)) | |
.build(); | |
return sendTransaction(creator, utx); | |
} | |
public String createAccount(String creator, String newAccountName, String domainName) throws NotFoundException, InternalServerException, IOException { | |
//todo make it transactional | |
//generate public key | |
Keypair keypair = crypto.generateKeypair(); | |
PublicKey pubkey = keypair.publicKey(); | |
setPubKey(newAccountName, pubkey); | |
PrivateKey prvkey = keypair.privateKey(); | |
setPrivKey(newAccountName, prvkey); | |
UnsignedTx utx = txBuilder.creatorAccountId(creator) | |
.createdTime(BigInteger.valueOf(System.currentTimeMillis())) | |
.createAccount(newAccountName, domainName, pubkey) | |
.build(); | |
return sendTransaction(creator, utx); | |
} | |
public String createAsset(String creator, String assetName, String domainName, double precision) throws NotFoundException, InternalServerException { | |
UnsignedTx utx = txBuilder.creatorAccountId(creator) | |
.createdTime(BigInteger.valueOf(System.currentTimeMillis())) | |
.createAsset(assetName, domainName, (short) precision) | |
.build(); | |
return sendTransaction(creator, utx); | |
} | |
public String createDomain(String creator, String domainName, String defaultRole) throws NotFoundException, InternalServerException { | |
UnsignedTx utx = txBuilder.creatorAccountId(creator) | |
.createdTime(BigInteger.valueOf(System.currentTimeMillis())) | |
.createDomain(domainName, defaultRole) | |
.build(); | |
return sendTransaction(creator, utx); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment