-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
051a24a
commit b37e1c3
Showing
2 changed files
with
121 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
117 changes: 117 additions & 0 deletions
117
core/src/main/java/org/bitcorej/chain/bip/BIPStateProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package org.bitcorej.chain.bip; | ||
|
||
import org.bitcoinj.core.ECKey; | ||
import org.bitcorej.chain.ChainState; | ||
import org.bitcorej.chain.KeyPair; | ||
import org.bitcorej.chain.Transaction; | ||
import org.bitcorej.utils.NumericUtil; | ||
import org.json.JSONObject; | ||
import org.web3j.crypto.Credentials; | ||
import org.web3j.crypto.Keys; | ||
import org.web3j.crypto.Sign; | ||
import org.web3j.rlp.RlpEncoder; | ||
import org.web3j.rlp.RlpList; | ||
import org.web3j.rlp.RlpString; | ||
import org.web3j.rlp.RlpType; | ||
import org.web3j.utils.Bytes; | ||
import org.web3j.utils.Numeric; | ||
|
||
import java.math.BigInteger; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public class BIPStateProvider implements ChainState { | ||
@Override | ||
public KeyPair generateKeyPair(String secret) { | ||
ECKey ecKey = ECKey.fromPrivate(NumericUtil.hexToBytes(secret)); | ||
String address = Numeric.prependHexPrefix(Keys.getAddress(Sign.publicKeyFromPrivate(ecKey.getPrivKey()))); | ||
return new KeyPair(ecKey.getPrivateKeyAsHex(), address.replace("0x", "Mx")); | ||
} | ||
|
||
@Override | ||
public KeyPair generateKeyPair() { | ||
return this.generateKeyPair(new ECKey().getPrivateKeyAsHex()); | ||
} | ||
|
||
@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) { | ||
JSONObject jsonObject = new JSONObject(rawTx); | ||
BigInteger nonce = BigInteger.valueOf(jsonObject.getInt("nonce")); | ||
BigInteger gasPrice = new BigInteger(jsonObject.getString("gasPrice")); | ||
BigInteger value = new BigInteger(jsonObject.getString("value")); | ||
String to = jsonObject.getString("to"); | ||
Sign.SignatureData signatureData = Sign.signMessage( | ||
encode(nonce, gasPrice, to, value, null), Credentials.create(keys.get(0)).getEcKeyPair()); | ||
JSONObject packed = new JSONObject(); | ||
packed.put("raw", Numeric.prependHexPrefix(NumericUtil.bytesToHex(encode(nonce, gasPrice, to, value, signatureData)))); | ||
return packed.toString(); | ||
} | ||
|
||
byte[] encode(BigInteger nonce, BigInteger gasPrice, String to, BigInteger value, Sign.SignatureData signatureData) { | ||
List<RlpType> values = new ArrayList<>(); | ||
// nonce | ||
values.add(RlpString.create(nonce)); | ||
// chainId: mainnet | ||
values.add(RlpString.create(NumericUtil.hexToBytes("0x01"))); | ||
// gasPrice | ||
values.add(RlpString.create(gasPrice)); | ||
// gasCoin | ||
values.add(RlpString.create(strrpad(10, "BIP"))); | ||
// type: SEND | ||
values.add(RlpString.create(BigInteger.valueOf(1))); | ||
// data | ||
values.add(RlpString.create(encodeSendCoin(to, value))); | ||
// payload | ||
values.add(RlpString.create(new byte[]{})); | ||
// serviceData | ||
values.add(RlpString.create(new byte[]{})); | ||
// signatureType: Single | ||
values.add(RlpString.create(BigInteger.valueOf(1))); | ||
// signatureData | ||
if (signatureData != null) { | ||
List<RlpType> signature = new ArrayList<>(); | ||
signature.add(RlpString.create(signatureData.getV())); | ||
signature.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getR()))); | ||
signature.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getS()))); | ||
values.add(RlpString.create(RlpEncoder.encode(new RlpList(signature)))); | ||
} | ||
RlpList rlpList = new RlpList(values); | ||
return RlpEncoder.encode(rlpList); | ||
} | ||
String strrpad(int size, String input) { | ||
int offset = size - input.length(); | ||
char[] inBytes = input.toCharArray(); | ||
char[] out = new char[size]; | ||
|
||
for (int i = 0, s = 0; i < size; i++) { | ||
if (i < input.length()) { | ||
out[i] = inBytes[i]; | ||
} else { | ||
out[i] = '\0'; | ||
} | ||
} | ||
return new String(out); | ||
} | ||
|
||
byte[] encodeSendCoin(String to, BigInteger value) { | ||
List<RlpType> values = new ArrayList<>(); | ||
// coin | ||
values.add(RlpString.create(strrpad(10, "BIP"))); | ||
// to | ||
values.add(RlpString.create(Numeric.hexStringToByteArray(to.substring(2)))); | ||
// value | ||
values.add(RlpString.create(value)); | ||
RlpList rlpList = new RlpList(values); | ||
return RlpEncoder.encode(rlpList); | ||
} | ||
} |