Skip to content

Commit

Permalink
Feat/implement construction hash (#80)
Browse files Browse the repository at this point in the history
* feat: implement /construction/hash

* chore: updated readme

* chore: updated readme
  • Loading branch information
Kammerlo authored Mar 8, 2024
1 parent 899803f commit 90134b1
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 38 deletions.
29 changes: 14 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,21 @@ to fetch the data from the node.
- [x] Integration test setup
- API calls
- Data API
- [x] /network/list
- [x] /network/status
- [x] /network/options
- [x] /block/*
- [ ] /mempool/*
- [x] /account/*
- [x] /network/list
- [x] /network/status
- [x] /network/options
- [x] /block/*
- [ ] /mempool/*
- [x] /account/*
- Construction API
- [x] /construction/derive
- [ ] /construction/preprocess
- [ ] /construction/metadata
- [ ] /construction/payloads
- [ ] /construction/combine
- [ ] /construction/parse
- [ ] /construction/hash
- [ ] /construction/submit

- [x] /construction/derive
- [ ] /construction/preprocess
- [ ] /construction/metadata
- [ ] /construction/payloads
- [ ] /construction/combine
- [ ] /construction/parse
- [x] /construction/hash
- [ ] /construction/submit

## Getting Started

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package org.cardanofoundation.rosetta.api.service;


public interface CardanoService {
import co.nstant.in.cbor.model.Array;

public interface CardanoService {
String getHashOfSignedTransaction(String signedTransaction);
Array decodeExtraData(String encoded);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
package org.cardanofoundation.rosetta.api.service.impl;

import co.nstant.in.cbor.model.Array;
import co.nstant.in.cbor.model.DataItem;
import com.bloxbean.cardano.client.common.cbor.CborSerializationUtil;
import com.bloxbean.cardano.client.crypto.Blake2bUtil;
import com.bloxbean.cardano.client.transaction.spec.Transaction;
import com.bloxbean.cardano.client.transaction.spec.TransactionBody;
import com.bloxbean.cardano.client.util.HexUtil;
import lombok.extern.slf4j.Slf4j;
import org.cardanofoundation.rosetta.api.exception.ExceptionFactory;
import org.cardanofoundation.rosetta.api.service.CardanoService;
import org.cardanofoundation.rosetta.api.util.CardanoAddressUtils;
import org.springframework.stereotype.Service;


Expand All @@ -10,5 +19,43 @@
@Service
public class CardanoServiceImpl implements CardanoService {

@Override
public String getHashOfSignedTransaction(String signedTransaction) {
try {
log.info("[getHashOfSignedTransaction] About to hash signed transaction {}",
signedTransaction);
byte[] signedTransactionBytes = HexUtil.decodeHexString(signedTransaction);
log.info(
"[getHashOfSignedTransaction] About to parse transaction from signed transaction bytes");
Transaction parsed = Transaction.deserialize(signedTransactionBytes);
log.info("[getHashOfSignedTransaction] Returning transaction hash");
TransactionBody body = parsed.getBody();
byte[] hashBuffer;
if (body == null ||
CborSerializationUtil.serialize(body.serialize())
== null) {
hashBuffer = null;
} else {
hashBuffer = Blake2bUtil.blake2bHash256(
com.bloxbean.cardano.client.common.cbor.CborSerializationUtil.serialize(
body.serialize()));
}
return CardanoAddressUtils.hexFormatter(hashBuffer);
} catch (Exception error) {
log.error(error.getMessage()
+ "[getHashOfSignedTransaction] There was an error parsing signed transaction");
throw ExceptionFactory.parseSignedTransactionError();
}
}

@Override
public Array decodeExtraData(String encoded) {
try {
DataItem dataItem = com.bloxbean.cardano.client.common.cbor.CborSerializationUtil.deserialize(
HexUtil.decodeHexString(encoded));
return (Array) dataItem;
} catch (Exception e) {
throw ExceptionFactory.cantBuildSignedTransaction();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.cardanofoundation.rosetta.api.service.impl;

import co.nstant.in.cbor.CborException;
import co.nstant.in.cbor.model.Array;
import co.nstant.in.cbor.model.UnicodeString;
import com.bloxbean.cardano.client.exception.AddressExcepion;
import com.bloxbean.cardano.client.exception.CborDeserializationException;
import com.bloxbean.cardano.client.exception.CborSerializationException;
Expand All @@ -12,6 +14,7 @@

import org.cardanofoundation.rosetta.api.model.enumeration.NetworkEnum;
import org.cardanofoundation.rosetta.api.service.CardanoAddressService;
import org.cardanofoundation.rosetta.api.service.CardanoService;
import org.cardanofoundation.rosetta.api.service.ConstructionApiService;
import org.openapitools.client.model.*;
import org.springframework.stereotype.Service;
Expand All @@ -25,6 +28,7 @@
public class ConstructionApiServiceImpl implements ConstructionApiService {

private final CardanoAddressService cardanoAddressService;
private final CardanoService cardanoService;

@Override
public ConstructionDeriveResponse constructionDeriveService(ConstructionDeriveRequest constructionDeriveRequest) throws IllegalAccessException, CborSerializationException {
Expand Down Expand Up @@ -76,7 +80,12 @@ public ConstructionCombineResponse constructionCombineService(ConstructionCombin

@Override
public TransactionIdentifierResponse constructionHashService(ConstructionHashRequest constructionHashRequest) {
return null;
Array array = cardanoService.decodeExtraData(constructionHashRequest.getSignedTransaction());
log.info("[constructionHash] About to get hash of signed transaction");
String transactionHash = cardanoService.getHashOfSignedTransaction(
((UnicodeString) array.getDataItems().get(0)).getString());
log.info("[constructionHash] About to return hash of signed transaction");
return new TransactionIdentifierResponse(new TransactionIdentifier(transactionHash), null);
}

@Override
Expand Down
15 changes: 13 additions & 2 deletions postmanTests/Rosetta-java-env.postman_environment.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,20 @@
"value": "Base",
"type": "default",
"enabled": true
},
{
"key": "signedTransaction",
"value": "827901c43834613430303831383235383230326632336664386363613833356166323166336163333735626163363031663937656164373566326537393134336264663731666532633462653034336538663031303138323832353831643631626234306631613634376263383863316264366237333864623865623636333537643932363437346561356666643662616137366339666231393237313038323538316436316262343066316136343762633838633162643662373338646238656236363335376439323634373465613566666436626161373663396662313939633430303231393963343030333139303365386131303038313832353832303162343030643630616166333465616636646362616239626261343630303161323334393738383663663131303636663738343639333364333065356164336635383430366339323530383133356362303630313837613237303661646538313534373832383637623135323665393631356430363734326265356335366630333761623835383934633039386332616230373937313133336330343737626165653932616466333532376164376363383136663133653165346333363130343132303666356636a16a6f7065726174696f6e7381a6746f7065726174696f6e5f6964656e746966696572a265696e646578006d6e6574776f726b5f696e64657800647479706565696e707574667374617475736773756363657373676163636f756e74a16761646472657373783a616464723176786135707564786737376733736461646465636d773874766336686d796e79776e34396c6c747434666d766e3763706e6b63707866616d6f756e74a26576616c7565662d39303030306863757272656e6379a26673796d626f6c6341444168646563696d616c73066b636f696e5f6368616e6765a26f636f696e5f6964656e746966696572a16a6964656e7469666965727842326632336664386363613833356166323166336163333735626163363031663937656164373566326537393134336264663731666532633462653034336538663a316b636f696e5f616374696f6e6a636f696e5f7370656e74",
"enabled": true
},
{
"key": "hashedSignedTransaction",
"value": "333a6ccaaa639f7b451ce93764f54f654ef499fdb7b8b24374ee9d99eab9d795",
"type": "default",
"enabled": true
}
],
"_postman_variable_scope": "environment",
"_postman_exported_at": "2024-03-06T12:46:41.009Z",
"_postman_exported_using": "Postman/10.23.8"
"_postman_exported_at": "2024-03-07T11:54:40.373Z",
"_postman_exported_using": "Postman/10.23.10"
}
90 changes: 71 additions & 19 deletions postmanTests/rosetta-java.postman_collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -341,60 +341,87 @@
"response": []
},
{
"name": "/mempool",
"name": "/mempool/transaction",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\n \"network_identifier\": {\n \"blockchain\": \"cardano\",\n \"network\": \"{{networkId}}\"\n },\n \"metadata\": {\n }\n}",
"raw": "{\n \"network_identifier\": {\n \"blockchain\": \"cardano\",\n \"network\": \"{{networkId}}\"\n },\n \"transaction_identifier\": {\n \"hash\": {{mempoolTransaction}}\n },\n \"metadata\": {}\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{URL}}/mempool",
"raw": "{{URL}}/mempool/transaction",
"host": [
"{{URL}}"
],
"path": [
"mempool"
"mempool",
"transaction"
]
}
},
"response": []
},
{
"name": "/mempool/transaction",
"name": "/construction/derive",
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test('Status code is 200', function () {",
" pm.response.to.have.status(200);",
"})",
"",
"pm.test('Contains Json Body', function () {",
" pm.response.to.have.jsonBody('address');",
"})",
"",
"pm.test(\"Correct Address\", function () {",
" const testAccountBaseAddress = pm.environment.get('TestAccountBaseAddress');",
" var responseData = pm.response.json();",
" pm.expect(responseData).to.be.an('object');",
" pm.expect(responseData.address).to.eql(testAccountBaseAddress);",
"});",
"",
""
],
"type": "text/javascript"
}
}
],
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\n \"network_identifier\": {\n \"blockchain\": \"cardano\",\n \"network\": \"{{networkId}}\"\n },\n \"transaction_identifier\": {\n \"hash\": {{mempoolTransaction}}\n },\n \"metadata\": {}\n}",
"raw": "{\n \"network_identifier\": {\n \"blockchain\": \"cardano\",\n \"network\": \"{{networkId}}\"\n },\n \"public_key\": {\n \"hex_bytes\": \"{{TestAccountPubKeyHexBytes}}\",\n \"curve_type\": \"{{curveType}}\"\n },\n \"metadata\": {\n \"address_type\": \"{{address_type}}\",\n \"staking_credential\": {\n \"hex_bytes\": \"{{TestAccountStakePubKeyHex}}\",\n \"curve_type\": \"{{curveType}}\"\n }\n }\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{URL}}/mempool/transaction",
"raw": "{{URL}}/construction/derive",
"host": [
"{{URL}}"
],
"path": [
"mempool",
"transaction"
"construction",
"derive"
]
}
},
"response": []
},
{
"name": "/construction/derive",
"name": "/construction/hash",
"event": [
{
"listen": "test",
Expand All @@ -405,17 +432,16 @@
"})",
"",
"pm.test('Contains Json Body', function () {",
" pm.response.to.have.jsonBody('address');",
" pm.response.to.have.jsonBody('transaction_identifier');",
"})",
"",
"pm.test(\"Correct Address\", function () {",
" const testAccountBaseAddress = pm.environment.get('TestAccountBaseAddress');",
" const hashedSignedTransaction = pm.environment.get('hashedSignedTransaction');",
" var responseData = pm.response.json();",
" pm.expect(responseData).to.be.an('object');",
" pm.expect(responseData.address).to.eql(testAccountBaseAddress);",
"});",
"",
""
" pm.expect(responseData.transaction_identifier).to.be.an('object');",
" pm.expect(responseData.transaction_identifier.hash).to.eql(hashedSignedTransaction);",
"});"
],
"type": "text/javascript"
}
Expand All @@ -426,21 +452,21 @@
"header": [],
"body": {
"mode": "raw",
"raw": "{\n \"network_identifier\": {\n \"blockchain\": \"cardano\",\n \"network\": \"{{networkId}}\"\n },\n \"public_key\": {\n \"hex_bytes\": \"{{TestAccountPubKeyHexBytes}}\",\n \"curve_type\": \"{{curveType}}\"\n },\n \"metadata\": {\n \"address_type\": \"{{address_type}}\",\n \"staking_credential\": {\n \"hex_bytes\": \"{{TestAccountStakePubKeyHex}}\",\n \"curve_type\": \"{{curveType}}\"\n }\n }\n}",
"raw": "{\n \"network_identifier\": {\n \"blockchain\": \"cardano\",\n \"network\": \"devkit\"\n },\n \"signed_transaction\": \"{{signedTransaction}}\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{URL}}/construction/derive",
"raw": "{{URL}}/construction/hash",
"host": [
"{{URL}}"
],
"path": [
"construction",
"derive"
"hash"
]
}
},
Expand Down Expand Up @@ -472,6 +498,32 @@
}
},
"response": []
},
{
"name": "/mempool",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\n \"network_identifier\": {\n \"blockchain\": \"cardano\",\n \"network\": \"{{networkId}}\"\n },\n \"metadata\": { }\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{URL}}/mempool",
"host": [
"{{URL}}"
],
"path": [
"mempool"
]
}
},
"response": []
}
],
"variable": [
Expand Down

0 comments on commit 90134b1

Please sign in to comment.