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

Feature/long chainId #913

Merged
merged 11 commits into from Apr 23, 2019
29 changes: 29 additions & 0 deletions CONTRIBUTING.md
@@ -0,0 +1,29 @@
## How to contribute to web3j

Thank you for reading this! If you'd like to report a bug or join in the buidl-ing of web3j, then here are some notes on how to do that.

#### **Did you find a bug?**

* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/web3j/web3j/issues). If there is then please add any more information that you have, or give it a :+1:. This will help us prioritize work.

* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/web3j/web3j/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible, and a **code sample** or event better an **executable test case** demonstrating the expected behavior that is not occurring.

#### **Did you write a patch that fixes a bug?**

* Open a new pull request with the patch.

* Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable.

#### **Do you intend to add a new feature or change an existing one?**

* Suggest your change in the [gitter channel](https://gitter.im/web3j/web3j) then start writing code.

* Do not open an issue on GitHub until you have collected positive feedback about the change. GitHub issues are primarily intended for bug reports and fixes.

#### **Do you have questions about the source code?**

* Ask any question about how to use web3j should be directed to the [gitter channel](https://gitter.im/web3j/web3j)

## :heart: BUIDL :heart:

team web3j
21 changes: 21 additions & 0 deletions core/src/main/java/org/web3j/crypto/WalletUtils.java
Expand Up @@ -108,6 +108,27 @@ public static Bip39Wallet generateBip39Wallet(String password, File destinationD
return new Bip39Wallet(walletFile, mnemonic);
}

/**
* Generates a BIP-39 compatible Ethereum wallet using a mnemonic passed as argument.
*
* @param password Will be used for both wallet encryption and passphrase for BIP-39 seed
* @param mnemonic The mnemonic that will be used to generate the seed
* @param destinationDirectory The directory containing the wallet
* @return A BIP-39 compatible Ethereum wallet
* @throws CipherException if the underlying cipher is not available
* @throws IOException if the destination cannot be written to
*/
public static Bip39Wallet generateBip39WalletFromMnemonic(
String password, String mnemonic, File destinationDirectory)
throws CipherException, IOException {
byte[] seed = MnemonicUtils.generateSeed(mnemonic, password);
ECKeyPair privateKey = ECKeyPair.create(sha256(seed));

String walletFile = generateWalletFile(password, privateKey, destinationDirectory, false);

return new Bip39Wallet(walletFile, mnemonic);
}

public static Credentials loadCredentials(String password, String source)
throws IOException, CipherException {
return loadCredentials(password, new File(source));
Expand Down
22 changes: 11 additions & 11 deletions core/src/main/java/org/web3j/ens/Contracts.java
@@ -1,6 +1,6 @@
package org.web3j.ens;

import org.web3j.tx.ChainId;
import org.web3j.tx.ChainIdLong;

/**
* ENS registry contract addresses.
Expand All @@ -12,16 +12,16 @@ public class Contracts {
public static final String RINKEBY = "0xe7410170f87102df0055eb195163a03b7f2bff4a";

public static String resolveRegistryContract(String chainId) {
switch (Byte.valueOf(chainId)) {
case ChainId.MAINNET:
return MAINNET;
case ChainId.ROPSTEN:
return ROPSTEN;
case ChainId.RINKEBY:
return RINKEBY;
default:
throw new EnsResolutionException(
"Unable to resolve ENS registry contract for network id: " + chainId);
final Long chainIdLong = Long.parseLong(chainId);
if (chainIdLong.equals(ChainIdLong.MAINNET)) {
return MAINNET;
} else if (chainIdLong.equals(ChainIdLong.ROPSTEN)) {
return ROPSTEN;
} else if (chainIdLong.equals(ChainIdLong.RINKEBY)) {
return RINKEBY;
} else {
throw new EnsResolutionException(
"Unable to resolve ENS registry contract for network id: " + chainId);
}
}
}
1 change: 0 additions & 1 deletion core/src/main/java/org/web3j/ens/EnsResolver.java
Expand Up @@ -9,7 +9,6 @@
import org.web3j.protocol.core.methods.response.EthSyncing;
import org.web3j.protocol.core.methods.response.NetVersion;
import org.web3j.tx.ClientTransactionManager;
import org.web3j.tx.ManagedTransaction;
import org.web3j.tx.TransactionManager;
import org.web3j.tx.gas.DefaultGasProvider;
import org.web3j.utils.Numeric;
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/org/web3j/tx/ChainId.java
Expand Up @@ -4,6 +4,7 @@
* Ethereum chain ids as per
* <a href="https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md">EIP-155</a>.
*/
@Deprecated
public class ChainId {
public static final byte NONE = -1;
public static final byte MAINNET = 1;
Expand All @@ -16,3 +17,4 @@ public class ChainId {
public static final byte ETHEREUM_CLASSIC_MAINNET = 61;
public static final byte ETHEREUM_CLASSIC_TESTNET = 62;
}

14 changes: 14 additions & 0 deletions core/src/main/java/org/web3j/tx/ChainIdLong.java
@@ -0,0 +1,14 @@
package org.web3j.tx;

public class ChainIdLong {
public static final long NONE = -1;
public static final long MAINNET = 1;
public static final long EXPANSE_MAINNET = 2;
public static final long ROPSTEN = 3;
public static final long RINKEBY = 4;
public static final long ROOTSTOCK_MAINNET = 30;
public static final long ROOTSTOCK_TESTNET = 31;
public static final long KOVAN = 42;
public static final long ETHEREUM_CLASSIC_MAINNET = 61;
public static final long ETHEREUM_CLASSIC_TESTNET = 62;
}
8 changes: 4 additions & 4 deletions core/src/main/java/org/web3j/tx/RawTransactionManager.java
Expand Up @@ -29,11 +29,11 @@ public class RawTransactionManager extends TransactionManager {
private final Web3j web3j;
final Credentials credentials;

private final byte chainId;
private final long chainId;

protected TxHashVerifier txHashVerifier = new TxHashVerifier();

public RawTransactionManager(Web3j web3j, Credentials credentials, byte chainId) {
public RawTransactionManager(Web3j web3j, Credentials credentials, long chainId) {
super(web3j, credentials.getAddress());

this.web3j = web3j;
Expand All @@ -43,7 +43,7 @@ public RawTransactionManager(Web3j web3j, Credentials credentials, byte chainId)
}

public RawTransactionManager(
Web3j web3j, Credentials credentials, byte chainId,
Web3j web3j, Credentials credentials, long chainId,
TransactionReceiptProcessor transactionReceiptProcessor) {
super(transactionReceiptProcessor, credentials.getAddress());

Expand All @@ -54,7 +54,7 @@ public RawTransactionManager(
}

public RawTransactionManager(
Web3j web3j, Credentials credentials, byte chainId, int attempts, long sleepDuration) {
Web3j web3j, Credentials credentials, long chainId, int attempts, long sleepDuration) {
super(web3j, attempts, sleepDuration, credentials.getAddress());

this.web3j = web3j;
Expand Down
11 changes: 11 additions & 0 deletions core/src/test/java/org/web3j/crypto/WalletUtilsTest.java
Expand Up @@ -18,6 +18,7 @@
import static org.web3j.crypto.Hash.sha256;
import static org.web3j.crypto.SampleKeys.CREDENTIALS;
import static org.web3j.crypto.SampleKeys.KEY_PAIR;
import static org.web3j.crypto.SampleKeys.MNEMONIC;
import static org.web3j.crypto.SampleKeys.PASSWORD;
import static org.web3j.crypto.WalletUtils.isValidAddress;
import static org.web3j.crypto.WalletUtils.isValidPrivateKey;
Expand Down Expand Up @@ -48,6 +49,16 @@ public void testGenerateBip39Wallets() throws Exception {
assertEquals(credentials, WalletUtils.loadBip39Credentials(PASSWORD, wallet.getMnemonic()));
}

@Test
public void testGenerateBip39WalletFromMnemonic() throws Exception {
Bip39Wallet wallet = WalletUtils.generateBip39WalletFromMnemonic(
PASSWORD, MNEMONIC, tempDir);
byte[] seed = MnemonicUtils.generateSeed(wallet.getMnemonic(), PASSWORD);
Credentials credentials = Credentials.create(ECKeyPair.create(sha256(seed)));

assertEquals(credentials, WalletUtils.loadBip39Credentials(PASSWORD, wallet.getMnemonic()));
}

@Test
public void testGenerateFullNewWalletFile() throws Exception {
String fileName = WalletUtils.generateFullNewWalletFile(PASSWORD, tempDir);
Expand Down
9 changes: 3 additions & 6 deletions core/src/test/java/org/web3j/ens/EnsResolverTest.java
Expand Up @@ -6,19 +6,16 @@
import org.junit.Before;
import org.junit.Test;

import org.web3j.abi.TypeDecoder;
import org.web3j.abi.TypeEncoder;
import org.web3j.abi.datatypes.Utf8String;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.Web3jService;
import org.web3j.protocol.core.JsonRpc2_0Web3j;
import org.web3j.protocol.core.Request;
import org.web3j.protocol.core.methods.response.EthBlock;
import org.web3j.protocol.core.methods.response.EthCall;
import org.web3j.protocol.core.methods.response.EthSyncing;
import org.web3j.protocol.core.methods.response.NetVersion;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.ChainId;
import org.web3j.tx.ChainIdLong;
import org.web3j.utils.Numeric;

import static org.hamcrest.CoreMatchers.is;
Expand Down Expand Up @@ -51,7 +48,7 @@ public void testResolve() throws Exception {
configureLatestBlock(System.currentTimeMillis() / 1000); // block timestamp is in seconds

NetVersion netVersion = new NetVersion();
netVersion.setResult(Byte.toString(ChainId.MAINNET));
netVersion.setResult(Long.toString(ChainIdLong.MAINNET));

String resolverAddress =
"0x0000000000000000000000004c641fb9bad9b60ef180c31f56051ce826d21a9a";
Expand Down Expand Up @@ -81,7 +78,7 @@ public void testReverseResolve() throws Exception {
configureLatestBlock(System.currentTimeMillis() / 1000); // block timestamp is in seconds

NetVersion netVersion = new NetVersion();
netVersion.setResult(Byte.toString(ChainId.MAINNET));
netVersion.setResult(Long.toString(ChainIdLong.MAINNET));

String resolverAddress =
"0x0000000000000000000000004c641fb9bad9b60ef180c31f56051ce826d21a9a";
Expand Down
16 changes: 10 additions & 6 deletions crypto/src/main/java/org/web3j/crypto/Sign.java
Expand Up @@ -82,7 +82,7 @@ public static SignatureData signMessage(byte[] message, ECKeyPair keyPair, boole
int headerByte = recId + 27;

// 1 header + 32 bytes for R + 32 bytes for S
byte v = (byte) headerByte;
byte[] v = new byte[]{(byte) headerByte};
byte[] r = Numeric.toBytesPadded(sig.r, 32);
byte[] s = Numeric.toBytesPadded(sig.s, 32);

Expand Down Expand Up @@ -217,7 +217,7 @@ static BigInteger signedMessageHashToKey(
verifyPrecondition(r != null && r.length == 32, "r must be 32 bytes");
verifyPrecondition(s != null && s.length == 32, "s must be 32 bytes");

int header = signatureData.getV() & 0xFF;
int header = signatureData.getV()[0] & 0xFF;
// The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
// 0x1D = second key with even y, 0x1E = second key with odd y
if (header < 27 || header > 34) {
Expand Down Expand Up @@ -277,17 +277,21 @@ public static BigInteger publicFromPoint(byte[] bits) {
}

public static class SignatureData {
private final byte v;
private final byte[] v;
private final byte[] r;
private final byte[] s;

public SignatureData(byte v, byte[] r, byte[] s) {
this(new byte[]{v}, r, s);
}

public SignatureData(byte[] v, byte[] r, byte[] s) {
this.v = v;
this.r = r;
this.s = s;
}

public byte getV() {
public byte[] getV() {
return v;
}

Expand All @@ -310,7 +314,7 @@ public boolean equals(Object o) {

SignatureData that = (SignatureData) o;

if (v != that.v) {
if (!Arrays.equals(v, that.v)) {
return false;
}
if (!Arrays.equals(r, that.r)) {
Expand All @@ -321,7 +325,7 @@ public boolean equals(Object o) {

@Override
public int hashCode() {
int result = (int) v;
int result = Arrays.hashCode(v);
result = 31 * result + Arrays.hashCode(r);
result = 31 * result + Arrays.hashCode(s);
return result;
Expand Down
16 changes: 10 additions & 6 deletions crypto/src/main/java/org/web3j/crypto/SignedRawTransaction.java
Expand Up @@ -3,12 +3,14 @@
import java.math.BigInteger;
import java.security.SignatureException;

import org.web3j.utils.Numeric;

public class SignedRawTransaction extends RawTransaction {

private static final int CHAIN_ID_INC = 35;
private static final int LOWER_REAL_V = 27;

private Sign.SignatureData signatureData;
private final Sign.SignatureData signatureData;

public SignedRawTransaction(BigInteger nonce, BigInteger gasPrice,
BigInteger gasLimit, String to, BigInteger value, String data,
Expand All @@ -29,7 +31,7 @@ public String getFrom() throws SignatureException {
} else {
encodedTransaction = TransactionEncoder.encode(this, chainId.byteValue());
}
byte v = signatureData.getV();
BigInteger v = Numeric.toBigInt(signatureData.getV());
byte[] r = signatureData.getR();
byte[] s = signatureData.getS();
Sign.SignatureData signatureDataV = new Sign.SignatureData(getRealV(v), r, s);
Expand All @@ -44,9 +46,10 @@ public void verify(String from) throws SignatureException {
}
}

private byte getRealV(byte v) {
private byte getRealV(BigInteger bv) {
long v = bv.longValue();
if (v == LOWER_REAL_V || v == (LOWER_REAL_V + 1)) {
return v;
return (byte) v;
}
byte realV = LOWER_REAL_V;
int inc = 0;
Expand All @@ -57,11 +60,12 @@ private byte getRealV(byte v) {
}

public Integer getChainId() {
byte v = signatureData.getV();
BigInteger bv = Numeric.toBigInt(signatureData.getV());
long v = bv.longValue();
if (v == LOWER_REAL_V || v == (LOWER_REAL_V + 1)) {
return null;
}
Integer chainId = (v - CHAIN_ID_INC) / 2;
Integer chainId = (int)((v - CHAIN_ID_INC) / 2);
return chainId;
}
}
Expand Up @@ -20,7 +20,7 @@ public static RawTransaction decode(String hexTransaction) {
BigInteger value = ((RlpString) values.getValues().get(4)).asPositiveBigInteger();
String data = ((RlpString) values.getValues().get(5)).asString();
if (values.getValues().size() > 6) {
byte v = ((RlpString) values.getValues().get(6)).getBytes()[0];
byte[] v = ((RlpString) values.getValues().get(6)).getBytes();
byte[] r = Numeric.toBytesPadded(
Numeric.toBigInt(((RlpString) values.getValues().get(7)).getBytes()), 32);
byte[] s = Numeric.toBytesPadded(
Expand All @@ -33,5 +33,4 @@ public static RawTransaction decode(String hexTransaction) {
gasPrice, gasLimit, to, value, data);
}
}

}