Skip to content

Commit

Permalink
sup adk
Browse files Browse the repository at this point in the history
  • Loading branch information
pengpengliu committed Jul 21, 2020
1 parent dfa19e2 commit e2cad6a
Show file tree
Hide file tree
Showing 5 changed files with 512 additions and 0 deletions.
4 changes: 4 additions & 0 deletions core/src/main/java/org/bitcorej/chain/ChainStateProxy.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.bitcorej.chain;

import org.bitcorej.chain.ada.CardanoStateProvider;
import org.bitcorej.chain.adk.ADKStateProvider;
import org.bitcorej.chain.bch.BCHStateProvider;
import org.bitcorej.chain.bhd.BHDStateProvider;
import org.bitcorej.chain.binance.BinanceStateProvider;
Expand Down Expand Up @@ -189,6 +190,9 @@ public class ChainStateProxy implements ChainState, UTXOState, USDTState, XMRSta
SOLStateProvider sol = new SOLStateProvider();
services.put("SOL", sol);
services.put("SOL_MAIN", sol);
ADKStateProvider adk = new ADKStateProvider();
services.put("ADK", adk);
services.put("ADK_MAIN", adk);
}

private ChainState provider;
Expand Down
110 changes: 110 additions & 0 deletions core/src/main/java/org/bitcorej/chain/adk/ADKStateProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package org.bitcorej.chain.adk;

import org.apache.commons.lang3.ArrayUtils;
import org.bitcorej.chain.ChainState;
import org.bitcorej.chain.KeyPair;
import org.bitcorej.chain.Transaction;
import org.bitcorej.chain.adk.hash.Curl;
import org.bitcorej.chain.adk.hash.ISS;
import org.bitcorej.utils.NumericUtil;
import org.json.JSONArray;
import org.json.JSONObject;
import org.nervos.ckb.type.fixed.UInt32;

import java.security.SecureRandom;
import java.util.List;

public class ADKStateProvider implements ChainState {
String characters = "9ABCDEFGHIJKLMNOPQRSTUVWXYZ";

@Override
public KeyPair generateKeyPair(String secret) {
int[] seed = Converter.trits(secret);
int[] subseed = ISS.subseed(seed, 0);
int[] key = ISS.key(subseed, 2);
int[] digests = ISS.digests(key);
int[] addressTrits = ISS.address(digests);
String address = Converter.trytes(addressTrits);

int[] l = Converter.trits(address);
final int[] state = ArrayUtils.addAll(l, new int[729 - l.length]);
Curl.transform(state);
String checksum = Converter.trytes(state).substring(0, 9);
return new KeyPair(secret, address + checksum);
}

@Override
public KeyPair generateKeyPair() {
StringBuilder seed = new StringBuilder();
for (int i = 0; i < 81; i++) {
SecureRandom random = new SecureRandom();
byte[] bytes = new byte[4];
random.nextBytes(bytes);
UInt32 uInt32 = new UInt32(NumericUtil.bytesToHex(bytes));
long index = uInt32.getValue() % 27;
seed.append(characters, (int)index, (int)index + 1);
}
return generateKeyPair(seed.toString());
}

@Override
public Boolean validateTx(String rawTx, String requestTx) {
return null;
}

@Override
public Transaction decodeRawTransaction(String rawTx) {
return null;
}

@Override
public String signRawTransaction(String rawTx, List<String> keys) {
String secret = keys.get(0);
int[] seed = Converter.trits(secret);
int[] subseed = ISS.subseed(seed, 0);
int[] key = ISS.key(subseed, 2);

JSONArray bundle = new JSONArray(rawTx);

for (int i = 0; i < bundle.length(); i++) {
if (bundle.getJSONObject(i).getLong("value") < 0) {
String thisAddress = bundle.getJSONObject(i).getString("address");
JSONArray normalizedBundleHashArray = bundle.getJSONObject(i).getJSONArray("normalizedBundleHash");
int[] normalizedBundleHash = new int[normalizedBundleHashArray.length()];
for (int j = 0; j < normalizedBundleHashArray.length(); j++) {
normalizedBundleHash[j] = normalizedBundleHashArray.getInt(j);
}
int[] firstBundleFragment = getSliceOfArray(normalizedBundleHash,0, 27);
int[] firstFragment = getSliceOfArray(key,0, 6561);
int[] firstSignedFragment = ISS.signatureFragment(firstBundleFragment, firstFragment);
bundle.getJSONObject(i).put("signatureMessageFragment", Converter.trytes(firstSignedFragment));
for (int j = 0; j < bundle.length(); j++) {
if (bundle.getJSONObject(j).getString("address").equals(thisAddress) && bundle.getJSONObject(i).getLong("value") == 0) {
int[] secondFragment = getSliceOfArray(key, 6561, 2 * 6561);
int[] secondBundleFragment = getSliceOfArray(key,27, 27 * 2);
int[] secondSignedFragment = ISS.signatureFragment(secondBundleFragment, secondFragment);
bundle.getJSONObject(j).put("signatureMessageFragment", Converter.trytes(secondSignedFragment));
}
}
}
bundle.getJSONObject(i).remove("normalizedBundleHash");
}
return bundle.toString();
}

public static int[] getSliceOfArray(int[] arr,
int start, int end)
{

// Get the slice of the Array
int[] slice = new int[end - start];

// Copy elements of arr to slice
for (int i = 0; i < slice.length; i++) {
slice[i] = arr[start + i];
}

// return the slice
return slice;
}
}
136 changes: 136 additions & 0 deletions core/src/main/java/org/bitcorej/chain/adk/Converter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package org.bitcorej.chain.adk;

import java.util.Arrays;

public class Converter {

public static final int RADIX = 3;
public static final int MAX_TRIT_VALUE = (RADIX - 1) / 2, MIN_TRIT_VALUE = -MAX_TRIT_VALUE;

public static final int NUMBER_OF_TRITS_IN_A_BYTE = 5;
public static final int NUMBER_OF_TRITS_IN_A_TRYTE = 3;

static final int[][] BYTE_TO_TRITS_MAPPINGS = new int[243][];
static final int[][] TRYTE_TO_TRITS_MAPPINGS = new int[27][];

public static final String TRYTE_ALPHABET = "9ABCDEFGHIJKLMNOPQRSTUVWXYZ";

public static final int MIN_TRYTE_VALUE = -13, MAX_TRYTE_VALUE = 13;

static {

final int[] trits = new int[NUMBER_OF_TRITS_IN_A_BYTE];

for (int i = 0; i < 243; i++) {
BYTE_TO_TRITS_MAPPINGS[i] = Arrays.copyOf(trits, NUMBER_OF_TRITS_IN_A_BYTE);
increment(trits, NUMBER_OF_TRITS_IN_A_BYTE);
}

for (int i = 0; i < 27; i++) {
TRYTE_TO_TRITS_MAPPINGS[i] = Arrays.copyOf(trits, NUMBER_OF_TRITS_IN_A_TRYTE);
increment(trits, NUMBER_OF_TRITS_IN_A_TRYTE);
}
}

public static long longValue(final int[] trits, final int offset, final int size) {

long value = 0;
for (int i = size; i-- > 0; ) {
value = value * RADIX + trits[offset + i];
}
return value;
}

public static byte[] bytes(final int[] trits, final int offset, final int size) {

final byte[] bytes = new byte[(size + NUMBER_OF_TRITS_IN_A_BYTE - 1) / NUMBER_OF_TRITS_IN_A_BYTE];
for (int i = 0; i < bytes.length; i++) {

int value = 0;
for (int j = (size - i * NUMBER_OF_TRITS_IN_A_BYTE) < 5 ? (size - i * NUMBER_OF_TRITS_IN_A_BYTE) : NUMBER_OF_TRITS_IN_A_BYTE; j-- > 0; ) {
value = value * RADIX + trits[offset + i * NUMBER_OF_TRITS_IN_A_BYTE + j];
}
bytes[i] = (byte)value;
}

return bytes;
}

public static byte[] bytes(final int[] trits) {
return bytes(trits, 0, trits.length);
}

public static void getTrits(final byte[] bytes, final int[] trits) {

int offset = 0;
for (int i = 0; i < bytes.length && offset < trits.length; i++) {
System.arraycopy(BYTE_TO_TRITS_MAPPINGS[bytes[i] < 0 ? (bytes[i] + BYTE_TO_TRITS_MAPPINGS.length) : bytes[i]], 0, trits, offset, trits.length - offset < NUMBER_OF_TRITS_IN_A_BYTE ? (trits.length - offset) : NUMBER_OF_TRITS_IN_A_BYTE);
offset += NUMBER_OF_TRITS_IN_A_BYTE;
}
while (offset < trits.length) {
trits[offset++] = 0;
}
}

public static int[] trits(final String trytes) {

final int[] trits = new int[trytes.length() * NUMBER_OF_TRITS_IN_A_TRYTE];
for (int i = 0; i < trytes.length(); i++) {
System.arraycopy(TRYTE_TO_TRITS_MAPPINGS[TRYTE_ALPHABET.indexOf(trytes.charAt(i))], 0, trits, i * NUMBER_OF_TRITS_IN_A_TRYTE, NUMBER_OF_TRITS_IN_A_TRYTE);
}
return trits;
}

public static void copyTrits(final long value, final int[] destination, final int offset, final int size) {

long absoluteValue = value < 0 ? -value : value;
for (int i = 0; i < size; i++) {

int remainder = (int)(absoluteValue % RADIX);
absoluteValue /= RADIX;
if (remainder > MAX_TRIT_VALUE) {

remainder = MIN_TRIT_VALUE;
absoluteValue++;
}
destination[offset + i] = remainder;
}

if (value < 0) {
for (int i = 0; i < size; i++) {
destination[offset + i] = -destination[offset + i];
}
}
}

public static String trytes(final int[] trits, final int offset, final int size) {

final StringBuilder trytes = new StringBuilder();
for (int i = 0; i < (size + NUMBER_OF_TRITS_IN_A_TRYTE - 1) / NUMBER_OF_TRITS_IN_A_TRYTE; i++) {
int j = trits[offset + i * 3] + trits[offset + i * 3 + 1] * 3 + trits[offset + i * 3 + 2] * 9;
if (j < 0) {
j += TRYTE_ALPHABET.length();
}
trytes.append(TRYTE_ALPHABET.charAt(j));
}
return trytes.toString();
}

public static String trytes(final int[] trits) {
return trytes(trits, 0, trits.length);
}

public static int tryteValue(final int[] trits, final int offset) {
return trits[offset] + trits[offset + 1] * 3 + trits[offset + 2] * 9;
}

private static void increment(final int[] trits, final int size) {
for (int i = 0; i < size; i++) {
if (++trits[i] > Converter.MAX_TRIT_VALUE) {
trits[i] = Converter.MIN_TRIT_VALUE;
} else {
break;
}
}
}
}
61 changes: 61 additions & 0 deletions core/src/main/java/org/bitcorej/chain/adk/hash/Curl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.bitcorej.chain.adk.hash;

public class Curl {

public static final int HASH_LENGTH = 243;
private static final int STATE_LENGTH = 3 * HASH_LENGTH;

private static final int NUMBER_OF_ROUNDS = 27;
private static final int[] TRUTH_TABLE = {1, 0, -1, 1, -1, 0, -1, 1, 0};

private final int[] state = new int[STATE_LENGTH];

public void absorb(final int[] trits, int offset, int length) {

do {
System.arraycopy(trits, offset, state, 0, length < HASH_LENGTH ? length : HASH_LENGTH);
transform();
offset += HASH_LENGTH;
} while ((length -= HASH_LENGTH) > 0);
}


public void squeeze(final int[] trits, int offset, int length) {

do {
System.arraycopy(state, 0, trits, offset, length < HASH_LENGTH ? length : HASH_LENGTH);
transform();
offset += HASH_LENGTH;
} while ((length -= HASH_LENGTH) > 0);
}

private void transform() {

final int[] scratchpad = new int[STATE_LENGTH];
int scratchpadIndex = 0;
for (int round = 0; round < NUMBER_OF_ROUNDS; round++) {
System.arraycopy(state, 0, scratchpad, 0, STATE_LENGTH);
for (int stateIndex = 0; stateIndex < STATE_LENGTH; stateIndex++) {
state[stateIndex] = TRUTH_TABLE[scratchpad[scratchpadIndex] + scratchpad[scratchpadIndex += (scratchpadIndex < 365 ? 364 : -365)] * 3 + 4];
}
}
}

public static void transform(int[] state) {
final int[] scratchpad = new int[STATE_LENGTH];
int scratchpadIndex = 0;
for (int round = 0; round < NUMBER_OF_ROUNDS; round++) {
System.arraycopy(state, 0, scratchpad, 0, STATE_LENGTH);
for (int stateIndex = 0; stateIndex < STATE_LENGTH; stateIndex++) {
state[stateIndex] = TRUTH_TABLE[scratchpad[scratchpadIndex] + scratchpad[scratchpadIndex += (scratchpadIndex < 365 ? 364 : -365)] * 3 + 4];
}
}
}

public void reset() {
for (int stateIndex = 0; stateIndex < STATE_LENGTH; stateIndex++) {
state[stateIndex] = 0;
}
}

}
Loading

0 comments on commit e2cad6a

Please sign in to comment.