Merge origin/master
This commit is contained in:
commit
f539e8951d
4 changed files with 84 additions and 42 deletions
|
@ -72,9 +72,9 @@ public class Main {
|
||||||
|
|
||||||
// test.testBip39Opertion();
|
// test.testBip39Opertion();
|
||||||
|
|
||||||
// test.testAccountNamebyAddress();
|
test.testAccountNamebyAddress();
|
||||||
|
|
||||||
test.testAccountNameById();
|
// test.testAccountNameById();
|
||||||
|
|
||||||
// test.testRelativeAccountHistory();
|
// test.testRelativeAccountHistory();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.lang.reflect.Type;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -179,7 +180,7 @@ public class Test {
|
||||||
// return new String(Base64.encode(sigData), Charset.forName("UTF-8"));
|
// return new String(Base64.encode(sigData), Charset.forName("UTF-8"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] testTransactionSerialization(long head_block_number, String head_block_id, long relative_expiration) {
|
public void testTransactionSerialization(long head_block_number, String head_block_id, long relative_expiration) {
|
||||||
BlockData blockData = new BlockData(head_block_number, head_block_id, relative_expiration);
|
BlockData blockData = new BlockData(head_block_number, head_block_id, relative_expiration);
|
||||||
|
|
||||||
ArrayList<BaseOperation> operations = new ArrayList<BaseOperation>();
|
ArrayList<BaseOperation> operations = new ArrayList<BaseOperation>();
|
||||||
|
@ -192,7 +193,6 @@ public class Test {
|
||||||
byte[] serializedTransaction = this.transaction.toBytes();
|
byte[] serializedTransaction = this.transaction.toBytes();
|
||||||
System.out.println("Serialized transaction");
|
System.out.println("Serialized transaction");
|
||||||
System.out.println(Util.bytesToHex(serializedTransaction));
|
System.out.println(Util.bytesToHex(serializedTransaction));
|
||||||
return serializedTransaction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWebSocketTransfer() throws IOException {
|
public void testWebSocketTransfer() throws IOException {
|
||||||
|
@ -340,12 +340,15 @@ public class Test {
|
||||||
.setDestination(new UserAccount("1.2.129848"))
|
.setDestination(new UserAccount("1.2.129848"))
|
||||||
.setAmount(new AssetAmount(UnsignedLong.valueOf(100), new Asset("1.3.120")))
|
.setAmount(new AssetAmount(UnsignedLong.valueOf(100), new Asset("1.3.120")))
|
||||||
.setFee(new AssetAmount(UnsignedLong.valueOf(264174), new Asset("1.3.0")))
|
.setFee(new AssetAmount(UnsignedLong.valueOf(264174), new Asset("1.3.0")))
|
||||||
.setBlockData(new BlockData(43408, 1430521623, 1479231969))
|
.setBlockData(new BlockData(Main.REF_BLOCK_NUM, Main.REF_BLOCK_PREFIX, Main.RELATIVE_EXPIRATION))
|
||||||
.setPrivateKey(DumpedPrivateKey.fromBase58(null, Main.WIF).getKey())
|
.setPrivateKey(DumpedPrivateKey.fromBase58(null, Main.WIF).getKey())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
ArrayList<Serializable> transactionList = new ArrayList<>();
|
ArrayList<Serializable> transactionList = new ArrayList<>();
|
||||||
transactionList.add(transaction);
|
transactionList.add(transaction);
|
||||||
|
|
||||||
|
byte[] signature = transaction.getGrapheneSignature();
|
||||||
|
System.out.println(Util.bytesToHex(signature));
|
||||||
ApiCall call = new ApiCall(4, "call", "broadcast_transaction", transactionList, "2.0", 1);
|
ApiCall call = new ApiCall(4, "call", "broadcast_transaction", transactionList, "2.0", 1);
|
||||||
String jsonCall = call.toJsonString();
|
String jsonCall = call.toJsonString();
|
||||||
System.out.println("json call");
|
System.out.println("json call");
|
||||||
|
@ -402,7 +405,7 @@ public class Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTransactionBroadcastSequence() {
|
public void testTransactionBroadcastSequence() {
|
||||||
String url = "ws://api.devling.xyz:8088";
|
String url = Test.OPENLEDGER_WITNESS_URL;
|
||||||
WitnessResponseListener listener = new WitnessResponseListener() {
|
WitnessResponseListener listener = new WitnessResponseListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(WitnessResponse response) {
|
public void onSuccess(WitnessResponse response) {
|
||||||
|
@ -428,20 +431,29 @@ public class Test {
|
||||||
|
|
||||||
ArrayList<Serializable> transactionList = new ArrayList<>();
|
ArrayList<Serializable> transactionList = new ArrayList<>();
|
||||||
transactionList.add(transaction);
|
transactionList.add(transaction);
|
||||||
ApiCall call = new ApiCall(4, "call", "broadcast_transaction", transactionList, "2.0", 1);
|
|
||||||
|
|
||||||
WebSocketFactory factory = new WebSocketFactory().setConnectionTimeout(5000);
|
transactionList.add(transaction);
|
||||||
try {
|
|
||||||
WebSocket mWebSocket = factory.createSocket(url);
|
SSLContext context = null;
|
||||||
mWebSocket.addListener(new TransactionBroadcastSequence(transaction, listener));
|
context = NaiveSSLContext.getInstance("TLS");
|
||||||
mWebSocket.connect();
|
WebSocketFactory factory = new WebSocketFactory();
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("IOException. Msg: " + e.getMessage());
|
// Set the custom SSL context.
|
||||||
} catch (WebSocketException e) {
|
factory.setSSLContext(context);
|
||||||
System.out.println("WebSocketException. Msg: " + e.getMessage());
|
|
||||||
}
|
WebSocket mWebSocket = factory.createSocket(OPENLEDGER_WITNESS_URL);
|
||||||
|
|
||||||
|
mWebSocket.addListener(new TransactionBroadcastSequence(transaction, listener));
|
||||||
|
mWebSocket.connect();
|
||||||
|
|
||||||
} catch (MalformedTransactionException e) {
|
} catch (MalformedTransactionException e) {
|
||||||
System.out.println("MalformedTransactionException. Msg: " + e.getMessage());
|
System.out.println("MalformedTransactionException. Msg: " + e.getMessage());
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println("IOException. Msg: " + e.getMessage());
|
||||||
|
} catch (WebSocketException e) {
|
||||||
|
System.out.println("WebSocketException. Msg: " + e.getMessage());
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
System.out.println("NoSuchAlgoritmException. Msg: "+e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,6 +626,18 @@ public class Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAccountNamebyAddress() {
|
public void testAccountNamebyAddress() {
|
||||||
|
WitnessResponseListener listener = new WitnessResponseListener() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(WitnessResponse response) {
|
||||||
|
System.out.println("onSuccess");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(BaseResponse.Error error) {
|
||||||
|
System.out.println("onError");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
BrainKey brainKey = new BrainKey(Main.BRAIN_KEY, 0);
|
BrainKey brainKey = new BrainKey(Main.BRAIN_KEY, 0);
|
||||||
Address address = new Address(brainKey.getPrivateKey());
|
Address address = new Address(brainKey.getPrivateKey());
|
||||||
try {
|
try {
|
||||||
|
@ -626,7 +650,7 @@ public class Test {
|
||||||
factory.setSSLContext(context);
|
factory.setSSLContext(context);
|
||||||
|
|
||||||
WebSocket mWebSocket = factory.createSocket(OPENLEDGER_WITNESS_URL);
|
WebSocket mWebSocket = factory.createSocket(OPENLEDGER_WITNESS_URL);
|
||||||
mWebSocket.addListener(new GetAccountsByAddress(address, mListener));
|
mWebSocket.addListener(new GetAccountsByAddress(address, listener));
|
||||||
mWebSocket.connect();
|
mWebSocket.connect();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("IOException. Msg: " + e.getMessage());
|
System.out.println("IOException. Msg: " + e.getMessage());
|
||||||
|
|
|
@ -73,24 +73,24 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
public List<BaseOperation> getOperations(){ return this.operations; }
|
public List<BaseOperation> getOperations(){ return this.operations; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains a signature of this transaction.
|
* Obtains a signature of this transaction. Please note that due to the current reliance on
|
||||||
|
* bitcoinj to generate the signatures, and due to the fact that it uses deterministic
|
||||||
|
* ecdsa signatures, we are slightly modifying the expiration time of the transaction while
|
||||||
|
* we look for a signature that will be accepted by the graphene network.
|
||||||
|
*
|
||||||
|
* This should then be called before any other serialization method.
|
||||||
* @return: A valid signature of the current transaction.
|
* @return: A valid signature of the current transaction.
|
||||||
*/
|
*/
|
||||||
public byte[] getSignature(){
|
public byte[] getGrapheneSignature(){
|
||||||
byte[] serializedTransaction = this.toBytes();
|
boolean isGrapheneCanonical = false;
|
||||||
Sha256Hash hash = Sha256Hash.wrap(Sha256Hash.hash(serializedTransaction));
|
byte[] sigData = null;
|
||||||
boolean isCanonical = false;
|
|
||||||
int recId = -1;
|
while(!isGrapheneCanonical) {
|
||||||
ECKey.ECDSASignature sig = null;
|
byte[] serializedTransaction = this.toBytes();
|
||||||
while(!isCanonical) {
|
Sha256Hash hash = Sha256Hash.wrap(Sha256Hash.hash(serializedTransaction));
|
||||||
sig = privateKey.sign(hash);
|
int recId = -1;
|
||||||
if(!sig.isCanonical()){
|
ECKey.ECDSASignature sig = privateKey.sign(hash);
|
||||||
// Signature was not canonical, retrying
|
|
||||||
continue;
|
|
||||||
}else{
|
|
||||||
// Signature is canonical
|
|
||||||
isCanonical = true;
|
|
||||||
}
|
|
||||||
// Now we have to work backwards to figure out the recId needed to recover the signature.
|
// Now we have to work backwards to figure out the recId needed to recover the signature.
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
ECKey k = ECKey.recoverFromSignature(i, sig, hash, privateKey.isCompressed());
|
ECKey k = ECKey.recoverFromSignature(i, sig, hash, privateKey.isCompressed());
|
||||||
|
@ -99,15 +99,24 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sigData = new byte[65]; // 1 header + 32 bytes for R + 32 bytes for S
|
||||||
|
int headerByte = recId + 27 + (privateKey.isCompressed() ? 4 : 0);
|
||||||
|
sigData[0] = (byte) headerByte;
|
||||||
|
System.arraycopy(Utils.bigIntegerToBytes(sig.r, 32), 0, sigData, 1, 32);
|
||||||
|
System.arraycopy(Utils.bigIntegerToBytes(sig.s, 32), 0, sigData, 33, 32);
|
||||||
|
|
||||||
|
// Further "canonicality" tests
|
||||||
|
if(((sigData[0] & 0x80) != 0) || (sigData[0] == 0) ||
|
||||||
|
((sigData[1] & 0x80) != 0) || ((sigData[32] & 0x80) != 0) ||
|
||||||
|
(sigData[32] == 0) || ((sigData[33] & 0x80) != 0)){
|
||||||
|
this.blockData.setRelativeExpiration(this.blockData.getRelativeExpiration() + 1);
|
||||||
|
}else{
|
||||||
|
isGrapheneCanonical = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int headerByte = recId + 27 + (privateKey.isCompressed() ? 4 : 0);
|
|
||||||
byte[] sigData = new byte[65]; // 1 header + 32 bytes for R + 32 bytes for S
|
|
||||||
sigData[0] = (byte)headerByte;
|
|
||||||
System.arraycopy(Utils.bigIntegerToBytes(sig.r, 32), 0, sigData, 1, 32);
|
|
||||||
System.arraycopy(Utils.bigIntegerToBytes(sig.s, 32), 0, sigData, 33, 32);
|
|
||||||
return sigData;
|
return sigData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method that creates a serialized byte array with compact information about this transaction
|
* Method that creates a serialized byte array with compact information about this transaction
|
||||||
* that is needed for the creation of a signature.
|
* that is needed for the creation of a signature.
|
||||||
|
@ -156,6 +165,10 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
public JsonObject toJsonObject() {
|
public JsonObject toJsonObject() {
|
||||||
JsonObject obj = new JsonObject();
|
JsonObject obj = new JsonObject();
|
||||||
|
|
||||||
|
// Getting the signature before anything else,
|
||||||
|
// since this might change the transaction expiration data slightly
|
||||||
|
byte[] signature = getGrapheneSignature();
|
||||||
|
|
||||||
// Formatting expiration time
|
// Formatting expiration time
|
||||||
Date expirationTime = new Date(blockData.getRelativeExpiration() * 1000);
|
Date expirationTime = new Date(blockData.getRelativeExpiration() * 1000);
|
||||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||||
|
@ -166,7 +179,7 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
|
|
||||||
// Adding signatures
|
// Adding signatures
|
||||||
JsonArray signatureArray = new JsonArray();
|
JsonArray signatureArray = new JsonArray();
|
||||||
signatureArray.add(Util.bytesToHex(getSignature()));
|
signatureArray.add(Util.bytesToHex(signature));
|
||||||
obj.add(KEY_SIGNATURES, signatureArray);
|
obj.add(KEY_SIGNATURES, signatureArray);
|
||||||
|
|
||||||
JsonArray operationsArray = new JsonArray();
|
JsonArray operationsArray = new JsonArray();
|
||||||
|
|
|
@ -64,7 +64,6 @@ public class GetAccountsByAddress extends WebSocketAdapter {
|
||||||
|
|
||||||
Type GetAccountByAddressResponse = new TypeToken<WitnessResponse<List<List<String>>>>(){}.getType();
|
Type GetAccountByAddressResponse = new TypeToken<WitnessResponse<List<List<String>>>>(){}.getType();
|
||||||
WitnessResponse<WitnessResponse<List<List<String>>>> witnessResponse = gson.fromJson(response, GetAccountByAddressResponse);
|
WitnessResponse<WitnessResponse<List<List<String>>>> witnessResponse = gson.fromJson(response, GetAccountByAddressResponse);
|
||||||
|
|
||||||
if (witnessResponse.error != null) {
|
if (witnessResponse.error != null) {
|
||||||
this.mListener.onError(witnessResponse.error);
|
this.mListener.onError(witnessResponse.error);
|
||||||
} else {
|
} else {
|
||||||
|
@ -73,6 +72,12 @@ public class GetAccountsByAddress extends WebSocketAdapter {
|
||||||
websocket.disconnect();
|
websocket.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFrameSent(WebSocket websocket, WebSocketFrame frame) throws Exception {
|
||||||
|
if(frame.isTextFrame())
|
||||||
|
System.out.println(">>> "+frame.getPayloadText());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(WebSocket websocket, WebSocketException cause) throws Exception {
|
public void onError(WebSocket websocket, WebSocketException cause) throws Exception {
|
||||||
mListener.onError(new BaseResponse.Error(cause.getMessage()));
|
mListener.onError(new BaseResponse.Error(cause.getMessage()));
|
||||||
|
|
Loading…
Reference in a new issue