use of org.ethereum.util.RLPList in project rskj by rsksmart.
the class BridgeSerializationUtilsTest method decodeTwoMock.
private RLPList decodeTwoMock(byte[] bytes, InnerListMode mode) {
RLPList list = decodeList(bytes);
if (mode == InnerListMode.LAST_ELEMENT) {
byte[] lastElementBytes = list.get(list.size() - 1).getRLPData();
RLPList innerList = decodeList(lastElementBytes);
list.set(list.size() - 1, innerList);
} else if (mode == InnerListMode.STARTING_WITH_FF_RECURSIVE) {
for (int i = 0; i < list.size(); i++) {
byte[] elementBytes = list.get(i).getRLPData();
if (elementBytes.length > 0 && elementBytes[0] == -1) {
RLPList innerList = decodeTwoMock(Arrays.copyOfRange(elementBytes, 1, elementBytes.length), mode);
list.set(i, innerList);
}
}
}
return list;
}
use of org.ethereum.util.RLPList in project rskj by rsksmart.
the class BridgeSerializationUtilsTest method mock_RLP_decode2_forMapOfHashesToLong.
private void mock_RLP_decode2_forMapOfHashesToLong() {
// Plain list with first elements being the size
// Sizes are 1 byte long
// e.g., for list [a,b,c] and a.size = 5, b.size = 7, c.size = 4, then:
// 03050704[a bytes][b bytes][c bytes]
when(RLP.decode2(any(byte[].class))).then((InvocationOnMock invocation) -> {
RLPList result = new RLPList();
byte[] arg = invocation.getArgumentAt(0, byte[].class);
// Odd byte -> long from byte
for (int i = 0; i < arg.length; i++) {
byte[] element;
if (i % 2 == 0) {
element = Hex.decode(charNTimes((char) arg[i], 64));
} else {
element = new byte[] { arg[i] };
}
result.add(() -> element);
}
return new ArrayList<>(Arrays.asList(result));
});
}
use of org.ethereum.util.RLPList in project rskj by rsksmart.
the class BridgeSerializationUtilsTest method decodeList.
private RLPList decodeList(byte[] bytes) {
// First byte => length of list (n)
// Subsequent n bytes => length of each of the n elements
// Subsequent bytes => elements
RLPList decoded = new RLPList();
int size = Byte.toUnsignedInt(bytes[0]);
int offset = size + 1;
for (int i = 1; i <= size; i++) {
int elementSize = Byte.toUnsignedInt(bytes[i]);
byte[] element = Arrays.copyOfRange(bytes, offset, offset + elementSize);
decoded.add(() -> element);
offset += elementSize;
}
return decoded;
}
use of org.ethereum.util.RLPList in project rskj by rsksmart.
the class BridgeSupportTest method addSignatureFromValidFederator.
/**
* Helper method to test addSignature() with a valid federatorPublicKey parameter and both valid/invalid signatures
* @param privateKeysToSignWith keys used to sign the tx. Federator key when we want to produce a valid signature, a random key when we want to produce an invalid signature
* @param numberOfInputsToSign There is just 1 input. 1 when testing the happy case, other values to test attacks/bugs.
* @param signatureCanonical Signature should be canonical. true when testing the happy case, false to test attacks/bugs.
* @param signTwice Sign again with the same key
* @param expectedResult "InvalidParameters", "PartiallySigned" or "FullySigned"
*/
private void addSignatureFromValidFederator(List<BtcECKey> privateKeysToSignWith, int numberOfInputsToSign, boolean signatureCanonical, boolean signTwice, String expectedResult) throws Exception {
// Federation is the genesis federation ATM
Federation federation = bridgeConstants.getGenesisFederation();
Repository repository = new RepositoryImpl(config);
final Keccak256 keccak256 = PegTestUtils.createHash3();
Repository track = repository.startTracking();
BridgeStorageProvider provider = new BridgeStorageProvider(track, PrecompiledContracts.BRIDGE_ADDR, config.getBlockchainConfig().getCommonConstants().getBridgeConstants());
BtcTransaction prevTx = new BtcTransaction(btcParams);
TransactionOutput prevOut = new TransactionOutput(btcParams, prevTx, Coin.FIFTY_COINS, federation.getAddress());
prevTx.addOutput(prevOut);
BtcTransaction t = new BtcTransaction(btcParams);
TransactionOutput output = new TransactionOutput(btcParams, t, Coin.COIN, new BtcECKey().toAddress(btcParams));
t.addOutput(output);
t.addInput(prevOut).setScriptSig(PegTestUtils.createBaseInputScriptThatSpendsFromTheFederation(federation));
provider.getRskTxsWaitingForSignatures().put(keccak256, t);
provider.save();
track.commit();
track = repository.startTracking();
List<LogInfo> logs = new ArrayList<>();
BridgeEventLogger eventLogger = new BridgeEventLoggerImpl(bridgeConstants, logs);
BridgeSupport bridgeSupport = new BridgeSupport(config, track, eventLogger, contractAddress, (Block) null);
Script inputScript = t.getInputs().get(0).getScriptSig();
List<ScriptChunk> chunks = inputScript.getChunks();
byte[] program = chunks.get(chunks.size() - 1).data;
Script redeemScript = new Script(program);
Sha256Hash sighash = t.hashForSignature(0, redeemScript, BtcTransaction.SigHash.ALL, false);
BtcECKey.ECDSASignature sig = privateKeysToSignWith.get(0).sign(sighash);
if (!signatureCanonical) {
sig = new BtcECKey.ECDSASignature(sig.r, BtcECKey.CURVE.getN().subtract(sig.s));
}
byte[] derEncodedSig = sig.encodeToDER();
List derEncodedSigs = new ArrayList();
for (int i = 0; i < numberOfInputsToSign; i++) {
derEncodedSigs.add(derEncodedSig);
}
bridgeSupport.addSignature(1, findPublicKeySignedBy(federation.getPublicKeys(), privateKeysToSignWith.get(0)), derEncodedSigs, keccak256.getBytes());
if (signTwice) {
// Create another valid signature with the same private key
ECDSASigner signer = new ECDSASigner();
ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(privateKeysToSignWith.get(0).getPrivKey(), BtcECKey.CURVE);
signer.init(true, privKey);
BigInteger[] components = signer.generateSignature(sighash.getBytes());
BtcECKey.ECDSASignature sig2 = new BtcECKey.ECDSASignature(components[0], components[1]).toCanonicalised();
bridgeSupport.addSignature(1, findPublicKeySignedBy(federation.getPublicKeys(), privateKeysToSignWith.get(0)), Lists.newArrayList(sig2.encodeToDER()), keccak256.getBytes());
}
if (privateKeysToSignWith.size() > 1) {
BtcECKey.ECDSASignature sig2 = privateKeysToSignWith.get(1).sign(sighash);
byte[] derEncodedSig2 = sig2.encodeToDER();
List derEncodedSigs2 = new ArrayList();
for (int i = 0; i < numberOfInputsToSign; i++) {
derEncodedSigs2.add(derEncodedSig2);
}
bridgeSupport.addSignature(1, findPublicKeySignedBy(federation.getPublicKeys(), privateKeysToSignWith.get(1)), derEncodedSigs2, keccak256.getBytes());
}
bridgeSupport.save();
track.commit();
provider = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, config.getBlockchainConfig().getCommonConstants().getBridgeConstants());
if ("FullySigned".equals(expectedResult)) {
Assert.assertTrue(provider.getRskTxsWaitingForSignatures().isEmpty());
Assert.assertThat(logs, is(not(empty())));
Assert.assertThat(logs, hasSize(3));
LogInfo releaseTxEvent = logs.get(2);
Assert.assertThat(releaseTxEvent.getTopics(), hasSize(1));
Assert.assertThat(releaseTxEvent.getTopics(), hasItem(Bridge.RELEASE_BTC_TOPIC));
BtcTransaction releaseTx = new BtcTransaction(bridgeConstants.getBtcParams(), ((RLPList) RLP.decode2(releaseTxEvent.getData()).get(0)).get(1).getRLPData());
Script retrievedScriptSig = releaseTx.getInput(0).getScriptSig();
Assert.assertEquals(4, retrievedScriptSig.getChunks().size());
Assert.assertEquals(true, retrievedScriptSig.getChunks().get(1).data.length > 0);
Assert.assertEquals(true, retrievedScriptSig.getChunks().get(2).data.length > 0);
} else {
Script retrievedScriptSig = provider.getRskTxsWaitingForSignatures().get(keccak256).getInput(0).getScriptSig();
Assert.assertEquals(4, retrievedScriptSig.getChunks().size());
// for "InvalidParameters"
boolean expectSignatureToBePersisted = false;
if ("PartiallySigned".equals(expectedResult)) {
expectSignatureToBePersisted = true;
}
Assert.assertEquals(expectSignatureToBePersisted, retrievedScriptSig.getChunks().get(1).data.length > 0);
Assert.assertEquals(false, retrievedScriptSig.getChunks().get(2).data.length > 0);
}
}
use of org.ethereum.util.RLPList in project rskj by rsksmart.
the class BridgeSupportTest method addSignatureCreateEventLog.
@Test
public void addSignatureCreateEventLog() throws Exception {
// Setup
Federation federation = bridgeConstants.getGenesisFederation();
Repository track = new RepositoryImpl(config).startTracking();
BridgeStorageProvider provider = new BridgeStorageProvider(track, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants);
// Build prev btc tx
BtcTransaction prevTx = new BtcTransaction(btcParams);
TransactionOutput prevOut = new TransactionOutput(btcParams, prevTx, Coin.FIFTY_COINS, federation.getAddress());
prevTx.addOutput(prevOut);
// Build btc tx to be signed
BtcTransaction btcTx = new BtcTransaction(btcParams);
btcTx.addInput(prevOut).setScriptSig(PegTestUtils.createBaseInputScriptThatSpendsFromTheFederation(federation));
TransactionOutput output = new TransactionOutput(btcParams, btcTx, Coin.COIN, new BtcECKey().toAddress(btcParams));
btcTx.addOutput(output);
// Save btc tx to be signed
final Keccak256 rskTxHash = PegTestUtils.createHash3();
provider.getRskTxsWaitingForSignatures().put(rskTxHash, btcTx);
provider.save();
track.commit();
// Setup BridgeSupport
List<LogInfo> eventLogs = new ArrayList<>();
BridgeEventLogger eventLogger = new BridgeEventLoggerImpl(bridgeConstants, eventLogs);
BridgeSupport bridgeSupport = new BridgeSupport(config, track, eventLogger, contractAddress, null);
// Create signed hash of Btc tx
Script inputScript = btcTx.getInputs().get(0).getScriptSig();
List<ScriptChunk> chunks = inputScript.getChunks();
byte[] program = chunks.get(chunks.size() - 1).data;
Script redeemScript = new Script(program);
Sha256Hash sigHash = btcTx.hashForSignature(0, redeemScript, BtcTransaction.SigHash.ALL, false);
BtcECKey privateKeyToSignWith = ((BridgeRegTestConstants) bridgeConstants).getFederatorPrivateKeys().get(0);
BtcECKey.ECDSASignature sig = privateKeyToSignWith.sign(sigHash);
List derEncodedSigs = Collections.singletonList(sig.encodeToDER());
BtcECKey federatorPubKey = findPublicKeySignedBy(federation.getPublicKeys(), privateKeyToSignWith);
bridgeSupport.addSignature(1, federatorPubKey, derEncodedSigs, rskTxHash.getBytes());
Assert.assertEquals(1, eventLogs.size());
// Assert address that made the log
LogInfo result = eventLogs.get(0);
Assert.assertArrayEquals(PrecompiledContracts.BRIDGE_ADDR.getBytes(), result.getAddress());
// Assert log topics
Assert.assertEquals(1, result.getTopics().size());
Assert.assertEquals(Bridge.ADD_SIGNATURE_TOPIC, result.getTopics().get(0));
// Assert log data
Assert.assertNotNull(result.getData());
List<RLPElement> rlpData = RLP.decode2(result.getData());
Assert.assertEquals(1, rlpData.size());
RLPList dataList = (RLPList) rlpData.get(0);
Assert.assertEquals(3, dataList.size());
Assert.assertArrayEquals(btcTx.getHashAsString().getBytes(), dataList.get(0).getRLPData());
Assert.assertArrayEquals(federatorPubKey.getPubKeyHash(), dataList.get(1).getRLPData());
Assert.assertArrayEquals(rskTxHash.getBytes(), dataList.get(2).getRLPData());
}
Aggregations