Skip to content

Instantly share code, notes, and snippets.

@samanshahmohamadi
Created December 4, 2018 13:36
Show Gist options
  • Save samanshahmohamadi/256f40b618b77f2d5a89dbcf27ef8585 to your computer and use it in GitHub Desktop.
Save samanshahmohamadi/256f40b618b77f2d5a89dbcf27ef8585 to your computer and use it in GitHub Desktop.
Iroha WebApplication
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);
}
}
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