Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autoconfirm XMR trade if tx check was validated by proof service #4421

Closed
wants to merge 49 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
43e4809
Add basic support for validation for XMR transfer with tx key
chimp1984 Jul 26, 2020
78da1df
Add trade date
chimp1984 Jul 27, 2020
ca8f53c
Implement XMR tx proof autoconfirm feature
Aug 2, 2020
c6f1e52
Merge remote-tracking branch 'origin/master' into add-xmr-tx-key-serv…
Aug 27, 2020
ac10d71
Add XMR proof result status code TRADE_LIMIT_EXCEEDED
Aug 27, 2020
967e053
Rename XmrProofResult to AutoConfirmResult
Aug 28, 2020
e3bf073
Persist the auto confirm state of Trade object
Aug 28, 2020
cccc6de
Default to clearnet XMR proof providers when in dev mode
Aug 29, 2020
5501822
Merge branch 'master_upstream' into xmr
chimp1984 Aug 30, 2020
d9d0814
Re-word the XMR account creation message per @m52go
Aug 30, 2020
36e2f71
Update core/src/main/resources/i18n/displayStrings.properties
Aug 30, 2020
ca9f61e
Update core/src/main/resources/i18n/displayStrings.properties
Aug 30, 2020
3e728c6
- Remove AutoConfirmResult enum from protobuf and add a AutoConfirmRe…
chimp1984 Aug 30, 2020
008ae93
Add null check for name
chimp1984 Aug 30, 2020
2dbc464
- Change tolerance from 1 day to 2 hours.
chimp1984 Aug 30, 2020
07a7612
- Make REPEAT_REQUEST_PERIOD and MAX_REQUEST_PERIOD static
chimp1984 Aug 30, 2020
2f7b24d
- Add @Nullable
chimp1984 Aug 30, 2020
2f1566b
Add NO_MATCH_FOUND in comment
chimp1984 Aug 30, 2020
ed5078c
Add abstract AutoConfirmResult class to get better support if we want
chimp1984 Aug 30, 2020
e5aee1c
No functionality has been changed by that refactoring, just moved
chimp1984 Aug 30, 2020
bfab6ff
Replace success/failure with booleans
chimp1984 Aug 30, 2020
5143b1e
Apply suggested changes from code analysis
chimp1984 Aug 30, 2020
77c203e
No functional change, pure refactoring
chimp1984 Aug 30, 2020
219094e
Merge branch 'add-xmr-tx-key-service-2' into add-xmr-tx-key-service-3
chimp1984 Aug 30, 2020
67723fa
Do not pass over xmrAutoConfirmationManager to ProcessModel but use a
chimp1984 Aug 30, 2020
595c968
Various small cleanups...
chimp1984 Aug 30, 2020
2fb6256
Refactoring: Rename getTextStatus to getStatusAsDisplayString
chimp1984 Aug 30, 2020
94c84b6
Add @Override, cleanup
chimp1984 Aug 30, 2020
2a887e1
Improve SetXmrTxKeyWindow
chimp1984 Aug 30, 2020
867e023
Merge branch 'master_upstream' into add-xmr-tx-key-service-3
chimp1984 Aug 30, 2020
38ac145
Add devMode check for NO_MATCH case.
chimp1984 Aug 30, 2020
c6c8a3e
Refactoring:
chimp1984 Aug 31, 2020
213dffb
Refactoring:
chimp1984 Aug 31, 2020
b76357e
Refactoring:
chimp1984 Aug 31, 2020
ef9ac12
Refactoring:
chimp1984 Aug 31, 2020
0740f8d
Remove @nullable from socks5ProxyProvider param
chimp1984 Aug 31, 2020
6f56f90
Refactor:
chimp1984 Aug 31, 2020
40a7320
Refactor:
chimp1984 Aug 31, 2020
f8b5c30
Refactor:
chimp1984 Aug 31, 2020
4478222
Refactor:
chimp1984 Aug 31, 2020
8707053
Refactor:
chimp1984 Aug 31, 2020
a758880
Refactor:
chimp1984 Aug 31, 2020
0e2268d
Refactor:
chimp1984 Aug 31, 2020
f3ad669
Refactor:
chimp1984 Aug 31, 2020
aab478a
Refactor:
chimp1984 Aug 31, 2020
2967530
Max amount was set to 0.1 BTC, should be 1 BTC
chimp1984 Aug 31, 2020
4f0e574
Use static field for dev test values
chimp1984 Aug 31, 2020
e9e7b48
Various refactorings, bug fixes and improvements.
chimp1984 Aug 31, 2020
fabd6c8
Merge pull request #1 from chimp1984/add-xmr-tx-key-service-3
Aug 31, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
214 changes: 1 addition & 213 deletions assets/src/main/java/bisq/asset/CryptoNoteAddressValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,6 @@

package bisq.asset;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import java.math.BigInteger;

import java.util.Map;

/**
* {@link AddressValidator} for Base58-encoded Cryptonote addresses.
*
Expand All @@ -46,7 +39,7 @@ public CryptoNoteAddressValidator(long... validPrefixes) {
@Override
public AddressValidationResult validate(String address) {
try {
long prefix = MoneroBase58.decodeAddress(address, this.validateChecksum);
long prefix = CryptoNoteUtils.MoneroBase58.decodeAddress(address, this.validateChecksum);
for (long validPrefix : this.validPrefixes) {
if (prefix == validPrefix) {
return AddressValidationResult.validAddress();
Expand All @@ -58,208 +51,3 @@ public AddressValidationResult validate(String address) {
}
}
}

class Keccak {

private static final int BLOCK_SIZE = 136;
private static final int LONGS_PER_BLOCK = BLOCK_SIZE / 8;
private static final int KECCAK_ROUNDS = 24;
private static final long[] KECCAKF_RNDC = {
0x0000000000000001L, 0x0000000000008082L, 0x800000000000808aL,
0x8000000080008000L, 0x000000000000808bL, 0x0000000080000001L,
0x8000000080008081L, 0x8000000000008009L, 0x000000000000008aL,
0x0000000000000088L, 0x0000000080008009L, 0x000000008000000aL,
0x000000008000808bL, 0x800000000000008bL, 0x8000000000008089L,
0x8000000000008003L, 0x8000000000008002L, 0x8000000000000080L,
0x000000000000800aL, 0x800000008000000aL, 0x8000000080008081L,
0x8000000000008080L, 0x0000000080000001L, 0x8000000080008008L
};
private static final int[] KECCAKF_ROTC = {
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
};
private static final int[] KECCAKF_PILN = {
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
};

private static long rotateLeft(long value, int shift) {
return (value << shift) | (value >>> (64 - shift));
}

private static void keccakf(long[] st, int rounds) {
long[] bc = new long[5];

for (int round = 0; round < rounds; ++round) {
for (int i = 0; i < 5; ++i) {
bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20];
}

for (int i = 0; i < 5; i++) {
long t = bc[(i + 4) % 5] ^ rotateLeft(bc[(i + 1) % 5], 1);
for (int j = 0; j < 25; j += 5) {
st[j + i] ^= t;
}
}

long t = st[1];
for (int i = 0; i < 24; ++i) {
int j = KECCAKF_PILN[i];
bc[0] = st[j];
st[j] = rotateLeft(t, KECCAKF_ROTC[i]);
t = bc[0];
}

for (int j = 0; j < 25; j += 5) {
for (int i = 0; i < 5; i++) {
bc[i] = st[j + i];
}
for (int i = 0; i < 5; i++) {
st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
}
}

st[0] ^= KECCAKF_RNDC[round];
}
}

public static ByteBuffer keccak1600(ByteBuffer input) {
input.order(ByteOrder.LITTLE_ENDIAN);

int fullBlocks = input.remaining() / BLOCK_SIZE;
long[] st = new long[25];
for (int block = 0; block < fullBlocks; ++block) {
for (int index = 0; index < LONGS_PER_BLOCK; ++index) {
st[index] ^= input.getLong();
}
keccakf(st, KECCAK_ROUNDS);
}

ByteBuffer lastBlock = ByteBuffer.allocate(144).order(ByteOrder.LITTLE_ENDIAN);
lastBlock.put(input);
lastBlock.put((byte)1);
int paddingOffset = BLOCK_SIZE - 1;
lastBlock.put(paddingOffset, (byte)(lastBlock.get(paddingOffset) | 0x80));
lastBlock.rewind();

for (int index = 0; index < LONGS_PER_BLOCK; ++index) {
st[index] ^= lastBlock.getLong();
}

keccakf(st, KECCAK_ROUNDS);

ByteBuffer result = ByteBuffer.allocate(32);
result.slice().order(ByteOrder.LITTLE_ENDIAN).asLongBuffer().put(st, 0, 4);
return result;
}
}

class MoneroBase58 {

private static final String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
private static final BigInteger ALPHABET_SIZE = BigInteger.valueOf(ALPHABET.length());
private static final int FULL_DECODED_BLOCK_SIZE = 8;
private static final int FULL_ENCODED_BLOCK_SIZE = 11;
private static final BigInteger UINT64_MAX = new BigInteger("18446744073709551615");
private static final Map<Integer, Integer> DECODED_CHUNK_LENGTH = Map.of( 2, 1,
3, 2,
5, 3,
6, 4,
7, 5,
9, 6,
10, 7,
11, 8);

private static void decodeChunk(String input,
int inputOffset,
int inputLength,
byte[] decoded,
int decodedOffset,
int decodedLength) throws Exception {

BigInteger result = BigInteger.ZERO;

BigInteger order = BigInteger.ONE;
for (int index = inputOffset + inputLength; index != inputOffset; order = order.multiply(ALPHABET_SIZE)) {
char character = input.charAt(--index);
int digit = ALPHABET.indexOf(character);
if (digit == -1) {
throw new Exception("invalid character " + character);
}
result = result.add(order.multiply(BigInteger.valueOf(digit)));
if (result.compareTo(UINT64_MAX) > 0) {
throw new Exception("64-bit unsigned integer overflow " + result.toString());
}
}

BigInteger maxCapacity = BigInteger.ONE.shiftLeft(8 * decodedLength);
if (result.compareTo(maxCapacity) >= 0) {
throw new Exception("capacity overflow " + result.toString());
}

for (int index = decodedOffset + decodedLength; index != decodedOffset; result = result.shiftRight(8)) {
decoded[--index] = result.byteValue();
}
}

private static byte[] decode(String input) throws Exception {
if (input.length() == 0) {
return new byte[0];
}

int chunks = input.length() / FULL_ENCODED_BLOCK_SIZE;
int lastEncodedSize = input.length() % FULL_ENCODED_BLOCK_SIZE;
int lastChunkSize = lastEncodedSize > 0 ? DECODED_CHUNK_LENGTH.get(lastEncodedSize) : 0;

byte[] result = new byte[chunks * FULL_DECODED_BLOCK_SIZE + lastChunkSize];
int inputOffset = 0;
int resultOffset = 0;
for (int chunk = 0; chunk < chunks; ++chunk,
inputOffset += FULL_ENCODED_BLOCK_SIZE,
resultOffset += FULL_DECODED_BLOCK_SIZE) {
decodeChunk(input, inputOffset, FULL_ENCODED_BLOCK_SIZE, result, resultOffset, FULL_DECODED_BLOCK_SIZE);
}
if (lastChunkSize > 0) {
decodeChunk(input, inputOffset, lastEncodedSize, result, resultOffset, lastChunkSize);
}

return result;
}

private static long readVarInt(ByteBuffer buffer) {
long result = 0;
for (int shift = 0; ; shift += 7) {
byte current = buffer.get();
result += (current & 0x7fL) << shift;
if ((current & 0x80L) == 0) {
break;
}
}
return result;
}

public static long decodeAddress(String address, boolean validateChecksum) throws Exception {
byte[] decoded = decode(address);

int checksumSize = 4;
if (decoded.length < checksumSize) {
throw new Exception("invalid length");
}

ByteBuffer decodedAddress = ByteBuffer.wrap(decoded, 0, decoded.length - checksumSize);

long prefix = readVarInt(decodedAddress.slice());
if (!validateChecksum) {
return prefix;
}

ByteBuffer fastHash = Keccak.keccak1600(decodedAddress.slice());
int checksum = fastHash.getInt();
int expected = ByteBuffer.wrap(decoded, decoded.length - checksumSize, checksumSize).getInt();
if (checksum != expected) {
throw new Exception(String.format("invalid checksum %08X, expected %08X", checksum, expected));
}

return prefix;
}
}
Loading