diff --git a/pom.xml b/pom.xml index d072f024..14ef3c38 100644 --- a/pom.xml +++ b/pom.xml @@ -54,6 +54,7 @@ commons-io commons-io 2.6 + test junit diff --git a/src/main/java/dev/jlibra/KeyUtils.java b/src/main/java/dev/jlibra/KeyUtils.java index f448be68..313c5dd8 100644 --- a/src/main/java/dev/jlibra/KeyUtils.java +++ b/src/main/java/dev/jlibra/KeyUtils.java @@ -13,9 +13,13 @@ public class KeyUtils { - public static String toLibraAddress(byte[] publicKeyBytes) { + public static String toHexStringLibraAddress(byte[] publicKeyBytes) { + return new String(Hex.encode(toByteArrayLibraAddress(publicKeyBytes))); + } + + public static byte[] toByteArrayLibraAddress(byte[] publicKeyBytes) { SHA3.DigestSHA3 digestSHA3 = new SHA3.Digest256(); - return new String(Hex.encode(digestSHA3.digest(stripPublicKeyPrefix(publicKeyBytes)))); + return digestSHA3.digest(stripPublicKeyPrefix(publicKeyBytes)); } public static byte[] stripPublicKeyPrefix(byte[] pubKeyBytes) { diff --git a/src/main/java/dev/jlibra/admissioncontrol/AdmissionControl.java b/src/main/java/dev/jlibra/admissioncontrol/AdmissionControl.java new file mode 100644 index 00000000..a45ebbca --- /dev/null +++ b/src/main/java/dev/jlibra/admissioncontrol/AdmissionControl.java @@ -0,0 +1,149 @@ +package dev.jlibra.admissioncontrol; + +import static java.util.stream.Collectors.toList; + +import java.io.IOException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.protobuf.ByteString; + +import admission_control.AdmissionControlGrpc; +import admission_control.AdmissionControlGrpc.AdmissionControlBlockingStub; +import admission_control.AdmissionControlOuterClass.SubmitTransactionRequest; +import admission_control.AdmissionControlOuterClass.SubmitTransactionResponse; +import dev.jlibra.AccountState; +import dev.jlibra.KeyUtils; +import dev.jlibra.LibraHelper; +import dev.jlibra.admissioncontrol.query.GetAccountState; +import dev.jlibra.admissioncontrol.query.UpdateToLatestLedgerResult; +import dev.jlibra.admissioncontrol.transaction.SubmitTransactionResult; +import dev.jlibra.admissioncontrol.transaction.Transaction; +import dev.jlibra.admissioncontrol.transaction.TransactionArgument.Type; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import types.GetWithProof.GetAccountStateRequest; +import types.GetWithProof.RequestItem; +import types.GetWithProof.UpdateToLatestLedgerRequest; +import types.GetWithProof.UpdateToLatestLedgerResponse; +import types.Transaction.Program; +import types.Transaction.RawTransaction; +import types.Transaction.SignedTransaction; +import types.Transaction.TransactionArgument; +import types.Transaction.TransactionArgument.ArgType; + +public class AdmissionControl { + + private String host; + + private int port; + + public AdmissionControl(String host, int port) { + this.host = host; + this.port = port; + } + + private static Map jlibraArgumentTypeToGrpcArgumentType; + + static { + jlibraArgumentTypeToGrpcArgumentType = new HashMap<>(); + jlibraArgumentTypeToGrpcArgumentType.put(Type.ADDRESS, ArgType.ADDRESS); + jlibraArgumentTypeToGrpcArgumentType.put(Type.U64, ArgType.U64); + } + + public SubmitTransactionResult submitTransaction(PublicKey publicKey, PrivateKey privateKey, + Transaction transaction) { + + ManagedChannel channel = ManagedChannelBuilder.forAddress(host, port) + .usePlaintext() + .build(); + + AdmissionControlBlockingStub stub = AdmissionControlGrpc.newBlockingStub(channel); + + List transactionArguments = transaction.getProgram().getArguments().stream() + .map(txArgument -> TransactionArgument.newBuilder() + .setType(jlibraArgumentTypeToGrpcArgumentType.get(txArgument.type())) + .setData(ByteString.copyFrom(txArgument.toByteArray())) + .build()) + .collect(toList()); + + Program program = Program.newBuilder() + .addAllArguments(transactionArguments) + .setCode(readCodeFromStream(transaction)) + .addAllModules(new ArrayList()) + .build(); + + RawTransaction rawTransaction = RawTransaction.newBuilder() + .setProgram(program) + .setExpirationTime(transaction.getExpirationTime()) + .setGasUnitPrice(transaction.getGasUnitPrice()) + .setMaxGasAmount(transaction.getMaxGasAmount()) + .setSenderAccount(ByteString.copyFrom(KeyUtils.toByteArrayLibraAddress(publicKey.getEncoded()))) + .setSequenceNumber(transaction.getSequenceNumber()) + .build(); + + SignedTransaction signedTransaction = SignedTransaction.newBuilder() + .setRawTxnBytes(rawTransaction.toByteString()) + .setSenderPublicKey(ByteString.copyFrom(KeyUtils.stripPublicKeyPrefix(publicKey.getEncoded()))) + .setSenderSignature(ByteString.copyFrom(LibraHelper.signTransaction(rawTransaction, privateKey))) + .build(); + + SubmitTransactionRequest submitTransactionRequest = SubmitTransactionRequest.newBuilder() + .setSignedTxn(signedTransaction) + .build(); + + SubmitTransactionResponse response = stub.submitTransaction(submitTransactionRequest); + + channel.shutdown(); + + return new SubmitTransactionResult(response.getAcStatus(), response.getMempoolStatus(), response.getVmStatus()); + } + + private ByteString readCodeFromStream(Transaction transaction) { + try { + return ByteString.readFrom(transaction.getProgram().getCode()); + } catch (IOException e) { + throw new RuntimeException("Could not read move code from input stream", e); + } + } + + public UpdateToLatestLedgerResult updateToLatestLedger(List arguments) { + ManagedChannel channel = ManagedChannelBuilder.forAddress(host, port) + .usePlaintext() + .build(); + + AdmissionControlBlockingStub stub = AdmissionControlGrpc.newBlockingStub(channel); + + List requestItems = arguments.stream().map(argument -> { + GetAccountStateRequest getAccountStateRequest = GetAccountStateRequest.newBuilder() + .setAddress(ByteString.copyFrom(argument.getAddress())) + .build(); + + RequestItem requestItem = RequestItem.newBuilder() + .setGetAccountStateRequest(getAccountStateRequest) + .build(); + return requestItem; + }).collect(toList()); + + UpdateToLatestLedgerResponse response = stub.updateToLatestLedger(UpdateToLatestLedgerRequest.newBuilder() + .addAllRequestedItems(requestItems) + .build()); + + List accountStates = new ArrayList<>(); + + response.getResponseItemsList().forEach(responseItem -> { + accountStates.addAll(LibraHelper.readAccountStates(responseItem.getGetAccountStateResponse() + .getAccountStateWithProof())); + }); + + UpdateToLatestLedgerResult result = UpdateToLatestLedgerResult.create() + .withAccountStates(accountStates); + + return result; + } + +} diff --git a/src/main/java/dev/jlibra/admissioncontrol/query/GetAccountState.java b/src/main/java/dev/jlibra/admissioncontrol/query/GetAccountState.java new file mode 100644 index 00000000..f8c1f4dc --- /dev/null +++ b/src/main/java/dev/jlibra/admissioncontrol/query/GetAccountState.java @@ -0,0 +1,13 @@ +package dev.jlibra.admissioncontrol.query; + +public class GetAccountState { + private byte[] address; + + public GetAccountState(byte[] address) { + this.address = address; + } + + public byte[] getAddress() { + return address; + } +} diff --git a/src/main/java/dev/jlibra/admissioncontrol/query/UpdateToLatestLedgerResult.java b/src/main/java/dev/jlibra/admissioncontrol/query/UpdateToLatestLedgerResult.java new file mode 100644 index 00000000..6b6a1d55 --- /dev/null +++ b/src/main/java/dev/jlibra/admissioncontrol/query/UpdateToLatestLedgerResult.java @@ -0,0 +1,27 @@ +package dev.jlibra.admissioncontrol.query; + +import java.util.List; + +import dev.jlibra.AccountState; + +public class UpdateToLatestLedgerResult { + + private List accountStates; + + private UpdateToLatestLedgerResult() { + } + + public static UpdateToLatestLedgerResult create() { + return new UpdateToLatestLedgerResult(); + } + + public UpdateToLatestLedgerResult withAccountStates(List accountStates) { + this.accountStates = accountStates; + return this; + } + + public List getAccountStates() { + return accountStates; + } + +} diff --git a/src/main/java/dev/jlibra/admissioncontrol/transaction/AddressArgument.java b/src/main/java/dev/jlibra/admissioncontrol/transaction/AddressArgument.java new file mode 100644 index 00000000..ec970da0 --- /dev/null +++ b/src/main/java/dev/jlibra/admissioncontrol/transaction/AddressArgument.java @@ -0,0 +1,21 @@ +package dev.jlibra.admissioncontrol.transaction; + +public class AddressArgument implements TransactionArgument { + + private byte[] address; + + public AddressArgument(byte[] address) { + this.address = address; + } + + @Override + public byte[] toByteArray() { + return address; + } + + @Override + public Type type() { + return Type.ADDRESS; + } + +} diff --git a/src/main/java/dev/jlibra/admissioncontrol/transaction/Program.java b/src/main/java/dev/jlibra/admissioncontrol/transaction/Program.java new file mode 100644 index 00000000..45a58d77 --- /dev/null +++ b/src/main/java/dev/jlibra/admissioncontrol/transaction/Program.java @@ -0,0 +1,25 @@ +package dev.jlibra.admissioncontrol.transaction; + +import java.io.InputStream; +import java.util.List; + +public class Program { + + private InputStream code; + + private List arguments; + + public Program(InputStream code, List arguments) { + this.code = code; + this.arguments = arguments; + } + + public InputStream getCode() { + return code; + } + + public List getArguments() { + return arguments; + } + +} diff --git a/src/main/java/dev/jlibra/admissioncontrol/transaction/SubmitTransactionResult.java b/src/main/java/dev/jlibra/admissioncontrol/transaction/SubmitTransactionResult.java new file mode 100644 index 00000000..90bddc1f --- /dev/null +++ b/src/main/java/dev/jlibra/admissioncontrol/transaction/SubmitTransactionResult.java @@ -0,0 +1,38 @@ +package dev.jlibra.admissioncontrol.transaction; + +import admission_control.AdmissionControlOuterClass.AdmissionControlStatus; +import mempool.MempoolStatus; +import types.VmErrors.VMStatus; + +public class SubmitTransactionResult { + + // TODO: Create own enum types instead of putting grpc enums directly here + // Could also add the description texts for clearer errors + + private AdmissionControlStatus admissionControlStatus; + + private MempoolStatus.MempoolAddTransactionStatus mempoolStatus; + + private VMStatus vmStatus; + + public SubmitTransactionResult(AdmissionControlStatus admissionControlStatus, + MempoolStatus.MempoolAddTransactionStatus mempoolStatus, + VMStatus vmStatus) { + this.admissionControlStatus = admissionControlStatus; + this.mempoolStatus = mempoolStatus; + this.vmStatus = vmStatus; + } + + public AdmissionControlStatus getAdmissionControlStatus() { + return admissionControlStatus; + } + + public MempoolStatus.MempoolAddTransactionStatus getMempoolStatus() { + return mempoolStatus; + } + + public VMStatus getVmStatus() { + return vmStatus; + } + +} diff --git a/src/main/java/dev/jlibra/admissioncontrol/transaction/Transaction.java b/src/main/java/dev/jlibra/admissioncontrol/transaction/Transaction.java new file mode 100644 index 00000000..ba9ba2fd --- /dev/null +++ b/src/main/java/dev/jlibra/admissioncontrol/transaction/Transaction.java @@ -0,0 +1,67 @@ +package dev.jlibra.admissioncontrol.transaction; + +public class Transaction { + + private long sequenceNumber; + + private Program program; + + private long expirationTime; + + private long gasUnitPrice; + + private long maxGasAmount; + + private Transaction() { + } + + public static Transaction create() { + return new Transaction(); + } + + public Transaction withProgram(Program program) { + this.program = program; + return this; + } + + public Transaction withSequenceNumber(long sequenceNumber) { + this.sequenceNumber = sequenceNumber; + return this; + } + + public Transaction withExpirationTime(long expirationTime) { + this.expirationTime = expirationTime; + return this; + } + + public Transaction withGasUnitPrice(long gasUnitPrice) { + this.gasUnitPrice = gasUnitPrice; + return this; + } + + public Transaction withMaxGasAmount(long maxGasAmount) { + this.maxGasAmount = maxGasAmount; + return this; + } + + public long getSequenceNumber() { + return sequenceNumber; + } + + public Program getProgram() { + return program; + } + + public long getExpirationTime() { + return expirationTime; + } + + public long getGasUnitPrice() { + return gasUnitPrice; + } + + public long getMaxGasAmount() { + return maxGasAmount; + } + +} diff --git a/src/main/java/dev/jlibra/admissioncontrol/transaction/TransactionArgument.java b/src/main/java/dev/jlibra/admissioncontrol/transaction/TransactionArgument.java new file mode 100644 index 00000000..3c9e0e25 --- /dev/null +++ b/src/main/java/dev/jlibra/admissioncontrol/transaction/TransactionArgument.java @@ -0,0 +1,13 @@ +package dev.jlibra.admissioncontrol.transaction; + +public interface TransactionArgument { + + public enum Type { + U64, ADDRESS + } + + byte[] toByteArray(); + + Type type(); + +} diff --git a/src/main/java/dev/jlibra/admissioncontrol/transaction/U64Argument.java b/src/main/java/dev/jlibra/admissioncontrol/transaction/U64Argument.java new file mode 100644 index 00000000..d348b360 --- /dev/null +++ b/src/main/java/dev/jlibra/admissioncontrol/transaction/U64Argument.java @@ -0,0 +1,26 @@ +package dev.jlibra.admissioncontrol.transaction; + +import static java.nio.ByteOrder.LITTLE_ENDIAN; + +import java.nio.ByteBuffer; + +public class U64Argument implements TransactionArgument { + + private long value; + + public U64Argument(long value) { + this.value = value; + } + + @Override + public byte[] toByteArray() { + return ByteBuffer.allocate(Long.BYTES).order(LITTLE_ENDIAN).putLong(value) + .order(LITTLE_ENDIAN).array(); + } + + @Override + public Type type() { + return Type.U64; + } + +} diff --git a/src/main/java/dev/jlibra/example/GetAccountStateExample.java b/src/main/java/dev/jlibra/example/GetAccountStateExample.java index 9ea4bf78..77d2cec3 100644 --- a/src/main/java/dev/jlibra/example/GetAccountStateExample.java +++ b/src/main/java/dev/jlibra/example/GetAccountStateExample.java @@ -1,57 +1,27 @@ package dev.jlibra.example; +import static java.util.Arrays.asList; + import java.io.IOException; import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import org.bouncycastle.util.encoders.Hex; -import com.google.protobuf.ByteString; - -import admission_control.AdmissionControlGrpc; -import admission_control.AdmissionControlGrpc.AdmissionControlBlockingStub; -import dev.jlibra.AccountState; -import dev.jlibra.LibraHelper; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import types.GetWithProof.GetAccountStateRequest; -import types.GetWithProof.RequestItem; -import types.GetWithProof.UpdateToLatestLedgerRequest; -import types.GetWithProof.UpdateToLatestLedgerResponse; +import dev.jlibra.admissioncontrol.AdmissionControl; +import dev.jlibra.admissioncontrol.query.GetAccountState; +import dev.jlibra.admissioncontrol.query.UpdateToLatestLedgerResult; public class GetAccountStateExample { public static void main(String[] args) throws IOException { String address = "045d3e63dba85f759d66f9bed4a0e4c262d17f9713f25e846fdae63891837a98"; - ManagedChannel channel = ManagedChannelBuilder.forAddress("ac.testnet.libra.org", 8000) - .usePlaintext() - .build(); - - AdmissionControlBlockingStub stub = AdmissionControlGrpc.newBlockingStub(channel); - - GetAccountStateRequest getAccountStateRequest = GetAccountStateRequest.newBuilder() - .setAddress(ByteString.copyFrom(Hex.decode(address))) - .build(); + AdmissionControl admissionControl = new AdmissionControl("ac.testnet.libra.org", 8000); - RequestItem requestItem = RequestItem.newBuilder() - .setGetAccountStateRequest(getAccountStateRequest) - .build(); - - UpdateToLatestLedgerResponse response = stub.updateToLatestLedger(UpdateToLatestLedgerRequest.newBuilder() - .addAllRequestedItems(Arrays.asList(requestItem)) - .build()); - - List accountStates = new ArrayList<>(); - - response.getResponseItemsList().forEach(responseItem -> { - accountStates.addAll(LibraHelper.readAccountStates(responseItem.getGetAccountStateResponse() - .getAccountStateWithProof())); - }); + UpdateToLatestLedgerResult result = admissionControl + .updateToLatestLedger(asList(new GetAccountState(Hex.decode(address)))); - accountStates.forEach(accountState -> { + result.getAccountStates().forEach(accountState -> { System.out.println("Address:" + new String(Hex.encode(accountState.getAddress()))); System.out.println("Received events: " + accountState.getReceivedEvents()); System.out.println("Sent events: " + accountState.getSentEvents()); diff --git a/src/main/java/dev/jlibra/example/TransferExample.java b/src/main/java/dev/jlibra/example/TransferExample.java index 156d39b4..08733643 100644 --- a/src/main/java/dev/jlibra/example/TransferExample.java +++ b/src/main/java/dev/jlibra/example/TransferExample.java @@ -1,31 +1,22 @@ package dev.jlibra.example; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; +import static dev.jlibra.KeyUtils.toHexStringLibraAddress; +import static java.util.Arrays.asList; + import java.security.PrivateKey; import java.security.PublicKey; import java.security.Security; -import java.util.ArrayList; -import java.util.Arrays; import org.bouncycastle.util.encoders.Hex; -import com.google.protobuf.ByteString; - -import admission_control.AdmissionControlGrpc; -import admission_control.AdmissionControlGrpc.AdmissionControlBlockingStub; -import admission_control.AdmissionControlOuterClass.SubmitTransactionRequest; -import admission_control.AdmissionControlOuterClass.SubmitTransactionResponse; import dev.jlibra.KeyUtils; -import dev.jlibra.LibraHelper; +import dev.jlibra.admissioncontrol.AdmissionControl; +import dev.jlibra.admissioncontrol.transaction.AddressArgument; +import dev.jlibra.admissioncontrol.transaction.Program; +import dev.jlibra.admissioncontrol.transaction.SubmitTransactionResult; +import dev.jlibra.admissioncontrol.transaction.Transaction; +import dev.jlibra.admissioncontrol.transaction.U64Argument; import dev.jlibra.move.Move; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import types.Transaction.Program; -import types.Transaction.RawTransaction; -import types.Transaction.SignedTransaction; -import types.Transaction.TransactionArgument; -import types.Transaction.TransactionArgument.ArgType; public class TransferExample { @@ -36,63 +27,36 @@ public static void main(String[] args) throws Exception { "3051020101300506032b6570042204207422e9df27029f7b83c37035622f93cd0e9b3a2a705d0745d573252756fd8c888121008e23fbceaa5b7a038c8994ca8258c8815e6e9007e3de86598cd46357e5e60024"); PublicKey publicKey = KeyUtils.publicKeyFromHexString( "302a300506032b65700321008e23fbceaa5b7a038c8994ca8258c8815e6e9007e3de86598cd46357e5e60024"); - String fromAddress = "6674633c78e2e00c69fd6e027aa6d1db2abc2a6c80d78a3e129eaf33dd49ce1c"; String toAddress = "045d3e63dba85f759d66f9bed4a0e4c262d17f9713f25e846fdae63891837a98"; - long amount = 7; - - ManagedChannel channel = ManagedChannelBuilder.forAddress("ac.testnet.libra.org", 8000) - .usePlaintext() - .build(); - - AdmissionControlBlockingStub stub = AdmissionControlGrpc.newBlockingStub(channel); - - TransactionArgument arg = TransactionArgument.newBuilder() - .setType(ArgType.ADDRESS) - .setData(ByteString.copyFrom(Hex.decode(toAddress))) - .build(); - - TransactionArgument arg2 = TransactionArgument.newBuilder() - .setType(ArgType.U64) - .setData(ByteString - .copyFrom( - ByteBuffer.allocate(Long.BYTES).order(ByteOrder.LITTLE_ENDIAN).putLong(amount * 1000000) - .order(ByteOrder.LITTLE_ENDIAN).array())) - .build(); - - Program program = Program.newBuilder() - .addAllArguments(Arrays.asList(arg, arg2)) - .setCode(ByteString.copyFrom(Move.peerToPeerTransfer())) - .addAllModules(new ArrayList()) - .build(); - - RawTransaction rawTransaction = RawTransaction.newBuilder() - .setProgram(program) - .setExpirationTime(600) - .setGasUnitPrice(1) - .setMaxGasAmount(6000) - .setSenderAccount(ByteString.copyFrom(Hex.decode(fromAddress))) - .setSequenceNumber(0) - .build(); - - SignedTransaction signedTransaction = SignedTransaction.newBuilder() - .setRawTxnBytes(rawTransaction.toByteString()) - .setSenderPublicKey(ByteString.copyFrom(KeyUtils.stripPublicKeyPrefix(publicKey.getEncoded()))) - .setSenderSignature(ByteString.copyFrom(LibraHelper.signTransaction(rawTransaction, privateKey))) - .build(); - - SubmitTransactionRequest submitTransactionRequest = SubmitTransactionRequest.newBuilder() - .setSignedTxn(signedTransaction) - .build(); - - SubmitTransactionResponse response = stub.submitTransaction(submitTransactionRequest); + long amount = 8; + int sequenceNumber = 5; - Thread.sleep(2000); // add sleep to prevent premature closing of channel + System.out.println( + String.format("Sending from %s to %s", toHexStringLibraAddress(publicKey.getEncoded()), toAddress)); + + AdmissionControl admissionControl = new AdmissionControl("ac.testnet.libra.org", 8000); - System.out.println("response: " + response); + // Arguments for the peer to peer transaction + U64Argument amountArgument = new U64Argument(amount * 1000000); + AddressArgument addressArgument = new AddressArgument(Hex.decode(toAddress)); - channel.shutdown(); + Transaction transaction = Transaction.create() + .withSequenceNumber(sequenceNumber) + .withMaxGasAmount(6000) + .withGasUnitPrice(1) + .withExpirationTime(10000) + .withProgram( + new Program(Move.peerToPeerTransfer(), asList(addressArgument, amountArgument))); + SubmitTransactionResult result = admissionControl.submitTransaction(publicKey, privateKey, + transaction); + + System.out.println("Admission control status: " + result.getAdmissionControlStatus()); + System.out.println("Mempool status: " + result.getMempoolStatus()); + System.out.println("VM status: " + result.getVmStatus()); + + Thread.sleep(2000); // add sleep to prevent premature closing of channel } } diff --git a/src/main/java/dev/jlibra/move/Move.java b/src/main/java/dev/jlibra/move/Move.java index b6f02b66..fcddf705 100644 --- a/src/main/java/dev/jlibra/move/Move.java +++ b/src/main/java/dev/jlibra/move/Move.java @@ -1,15 +1,11 @@ package dev.jlibra.move; -import org.apache.commons.io.IOUtils; +import java.io.InputStream; public class Move { - public static byte[] peerToPeerTransfer() { - try { - return IOUtils.toByteArray(Move.class.getResourceAsStream("/move/peer_to_peer_transfer.bin")); - } catch (Exception e) { - throw new RuntimeException("Reading the transfer script file failed", e); - } + public static InputStream peerToPeerTransfer() { + return Move.class.getResourceAsStream("/move/peer_to_peer_transfer.bin"); } } diff --git a/src/test/java/dev/jlibra/KeyUtilsTest.java b/src/test/java/dev/jlibra/KeyUtilsTest.java index d1aab6ed..25c73b5b 100644 --- a/src/test/java/dev/jlibra/KeyUtilsTest.java +++ b/src/test/java/dev/jlibra/KeyUtilsTest.java @@ -31,7 +31,7 @@ public void testToLibraAddress() throws Exception { PublicKey publicKey = getKeyFactory().generatePublic(new X509EncodedKeySpec(Hex .decode(PUBLIC_KEY_HEX))); - assertThat(KeyUtils.toLibraAddress(publicKey.getEncoded()), + assertThat(KeyUtils.toHexStringLibraAddress(publicKey.getEncoded()), is("eb99fc3808a8e439c58f87935cbe6774e4cc83459b463ea0813b34ef96f0ba87")); } diff --git a/src/test/java/dev/jlibra/move/MoveTest.java b/src/test/java/dev/jlibra/move/MoveTest.java index 269edb21..5ba785d1 100644 --- a/src/test/java/dev/jlibra/move/MoveTest.java +++ b/src/test/java/dev/jlibra/move/MoveTest.java @@ -10,7 +10,7 @@ public class MoveTest { @Test public void testPeerToPeerTransfer() throws Exception { - assertThat(Move.peerToPeerTransfer(), + assertThat(toByteArray(Move.peerToPeerTransfer()), equalTo(toByteArray(MoveTest.this.getClass().getResourceAsStream("/move/peer_to_peer_transfer.bin")))); }