Skip to content

Commit

Permalink
Merge branch 'main' of github.com:XRPLF/XRPL4j into df/v3-dev-preview
Browse files Browse the repository at this point in the history
  • Loading branch information
sappenin committed May 18, 2022
2 parents fcb7ecc + 7cabef9 commit 56f267a
Show file tree
Hide file tree
Showing 4 changed files with 445 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand All @@ -22,20 +22,28 @@

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.google.common.collect.Lists;
import org.xrpl.xrpl4j.codec.addresses.AddressCodec;
import org.xrpl.xrpl4j.codec.addresses.UnsignedByteArray;
import org.xrpl.xrpl4j.codec.binary.BinaryCodecObjectMapperFactory;
import org.xrpl.xrpl4j.codec.binary.definitions.DefinitionsService;
import org.xrpl.xrpl4j.codec.binary.definitions.FieldInstance;
import org.xrpl.xrpl4j.codec.binary.serdes.BinaryParser;
import org.xrpl.xrpl4j.codec.binary.serdes.BinarySerializer;
import org.xrpl.xrpl4j.model.jackson.ObjectMapperFactory;
import org.xrpl.xrpl4j.model.transactions.Address;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* Codec for XRPL STObject type.
Expand Down Expand Up @@ -87,7 +95,6 @@ public STObjectType fromJson(JsonNode node) {
isUNLModify = false;
}


List<FieldWithValue<JsonNode>> fields = new ArrayList<>();
for (String fieldName : Lists.newArrayList(node.fieldNames())) {

Expand All @@ -98,7 +105,29 @@ public STObjectType fromJson(JsonNode node) {
continue;
}

JsonNode fieldNode = node.get(fieldName);
JsonNode fieldNode;
// rippled expects signers canonically based on address
if (fieldName.equals("Signers")) {
final AddressCodec addressCodec = AddressCodec.getInstance();
ArrayNode arrayNode = (ArrayNode) node.get(fieldName);
List<JsonNode> jsonNodeList = new ArrayList<>();
for (JsonNode x : arrayNode) {
jsonNodeList.add(x);
}
List<JsonNode> jsonNodesSorted = jsonNodeList.stream().sorted(
Comparator.comparing(
signature -> new BigInteger(addressCodec.decodeAccountId(
Address.of(signature.get("Signer").get("Account").asText())
).hexValue(), 16)
)
).collect(Collectors.toList());

final ObjectMapper objectMapper = ObjectMapperFactory.create();
fieldNode = objectMapper.createObjectNode().arrayNode().addAll(jsonNodesSorted);
} else {
fieldNode = node.get(fieldName);
}

definitionsService.getFieldInstance(fieldName)
.filter(FieldInstance::isSerialized)
.ifPresent(fieldInstance -> fields.add(FieldWithValue.<JsonNode>builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand All @@ -23,15 +23,11 @@
import static org.assertj.core.api.Assertions.assertThat;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.xrpl.xrpl4j.codec.binary.serdes.BinaryParser;
import org.xrpl.xrpl4j.codec.binary.types.STObjectType;
import org.xrpl.xrpl4j.codec.fixtures.FixtureUtils;
import org.xrpl.xrpl4j.codec.fixtures.data.WholeObject;

Expand Down Expand Up @@ -269,6 +265,33 @@ void encodeForMultiSigning() throws JsonProcessingException {
assertThat(encoder.encodeForMultiSigning(json, signerAccountId)).isEqualTo(expected);
}

@Test
public void encodePaymentWithSigners() throws JsonProcessingException {
String json = "{\"Account\":\"rGs8cFHMfJanAXVtn6e8Lz2iH8FtnGdexw\",\"Fee\":\"30\"," +
"\"Sequence\":6," +
"\"Signers\":" +
"[{\"Signer\":{\"Account\":\"rGDG5dYzvaNMaNGHAYGJKGH1vPBTHeD4fy\"," +
"\"TxnSignature\":\"F5354C2AEAE320FCE49CE18733EA6C27103989878E2C5561028292A09A0AE920792847982D26" +
"8392B8134EF4CA35159C170C40E51F5AFB4F1400DCC9287A3709\"," +
"\"SigningPubKey\":\"ED62267B5A9A0917D5F0D52531428294A80EEFEEB1DB595AED1C94964B35F79F2C\"}}," +
"{\"Signer\":{\"Account\":\"rwm8zSsHG5oTrHMTkKQFKCV3QDQEG1zHvB\"," +
"\"TxnSignature\":\"26A90616049EA684FDD4685726DF674815B48CBC1827D2F0D1DBC8537AC8508F715480AF70C426" +
"B35C193DE49C851831E767BF4AA51880CD1F90618E74B93D0C\"," +
"\"SigningPubKey\":\"ED9018780E2D6D454ED59E40DBEFA4681B7307940B45B67E4C8DE80DBA79626BB8\"}}]," +
"\"SigningPubKey\":\"\",\"Flags\":2147483648,\"Amount\":\"12345\"," +
"\"Destination\":\"rfA6dKpRbJfZo9HgAVGLJP3T2qPgQMA9QB\",\"TransactionType\":\"Payment\"}";

String expected = "1200002280000000240000000661400000000000303968400000000000001E73008114A510CC5A6" +
"84976D8986ADA04D2AC4A9C5B77ADD983144C29212A966F2C128FCEB5DB86F5C0A0635275B6F3E0107321ED9018780E" +
"2D6D454ED59E40DBEFA4681B7307940B45B67E4C8DE80DBA79626BB8744026A90616049EA684FDD4685726DF674815B" +
"48CBC1827D2F0D1DBC8537AC8508F715480AF70C426B35C193DE49C851831E767BF4AA51880CD1F90618E74B93D0C81" +
"146B31D3372135AEEB0AA33540B2FBAD8CA4C2EBE2E1E0107321ED62267B5A9A0917D5F0D52531428294A80EEFEEB1D" +
"B595AED1C94964B35F79F2C7440F5354C2AEAE320FCE49CE18733EA6C27103989878E2C5561028292A09A0AE9207928" +
"47982D268392B8134EF4CA35159C170C40E51F5AFB4F1400DCC9287A37098114A6DBFFB301F614A2F7B5E6B94392E17" +
"AAF898E9DE1F1";
assertThat(encoder.encode(json)).isEqualTo(expected);
}

@ParameterizedTest
@MethodSource("dataDrivenFixtures")
void dataDriven(WholeObject wholeObject) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.ripple.cryptoconditions.der.DerEncodingException;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
import org.xrpl.xrpl4j.codec.addresses.AddressCodec;
import org.xrpl.xrpl4j.codec.binary.XrplBinaryCodec;
import org.xrpl.xrpl4j.model.flags.Flags;
import org.xrpl.xrpl4j.model.flags.Flags.PaymentFlags;
Expand Down Expand Up @@ -58,12 +59,17 @@
import org.xrpl.xrpl4j.model.transactions.PaymentChannelCreate;
import org.xrpl.xrpl4j.model.transactions.PaymentChannelFund;
import org.xrpl.xrpl4j.model.transactions.SetRegularKey;
import org.xrpl.xrpl4j.model.transactions.Signer;
import org.xrpl.xrpl4j.model.transactions.SignerListSet;
import org.xrpl.xrpl4j.model.transactions.SignerWrapper;
import org.xrpl.xrpl4j.model.transactions.Transaction;
import org.xrpl.xrpl4j.model.transactions.TrustSet;
import org.xrpl.xrpl4j.model.transactions.XrpCurrencyAmount;

import java.math.BigInteger;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class BinarySerializationTests {

Expand Down Expand Up @@ -516,6 +522,110 @@ public void serializePaymentWithPaths() throws JsonProcessingException {
assertSerializesAndDeserializes(payment, expected);
}

@Test
public void submitMultisignedWithSignersOutOfOrder() throws JsonProcessingException {

Payment unsignedPayment = Payment.builder()
.account(Address.of("rBcTTDopDWefBJoRHkLQ4SXcJ7jmERsB54"))
.fee(XrpCurrencyAmount.ofDrops(20))
.sequence(UnsignedInteger.ONE)
.amount(XrpCurrencyAmount.ofDrops(12345))
.destination(Address.of("rB7KywQ7ewYrCTZimJBH7VSegnt8KYyVze"))
.build();

List<SignerWrapper> signers = Lists.newArrayList(
SignerWrapper.of(Signer.builder()
.account(Address.of("rPbYo1myPZq4JHbB7D587iR5rqBZ2L47J1"))
.signingPublicKey("ED5B9B29CC4C59DB744B59814AF3D891AF7217E403ED734BA598DBE16994DED7EC")
.transactionSignature("1DDF2D82C8C010F3ED4C4687AECD5977E60410EA89614E316CF26195A8336CD57B3026" +
"4471C54D5BA089A91EDC8321B16C2444CFE0F9385E6B2A37B7C758000E")
.build()
),
SignerWrapper.of(Signer.builder()
.account(Address.of("rEzLrF8UtmrvgS8JjXvmUr1dEZnxVCicnJ"))
.signingPublicKey("EDB53FEFAB30FA2AD6EDB6EA3F5F9E4976CF765B94472933E1DAE3088F9707DDD7")
.transactionSignature("FAB3FA0C72F1FDAC99EA31701983F8F4F89803D6F7DF5465A22378EFE4ADA1C993B86B3" +
"226AAE3A239553F6DCF95CDED8E8FEBBC1C5343D3089A04C758353F03")
.build()
)
);

Payment multiSigPayment = Payment.builder()
.from(unsignedPayment)
.signers(signers)
.build();

String expected = "1200002280000000240000000161400000000000303968400000000000001481147465E5C80EA" +
"A9829630FB52A2DBE5F47FF7B95E9831472DC52A028EF1F8317D87794DEC6036A7292D502F3E0107321EDB53FEFAB30" +
"FA2AD6EDB6EA3F5F9E4976CF765B94472933E1DAE3088F9707DDD77440FAB3FA0C72F1FDAC99EA31701983F8F4F89803" +
"D6F7DF5465A22378EFE4ADA1C993B86B3226AAE3A239553F6DCF95CDED8E8FEBBC1C5343D3089A04C758353F038114" +
"A46957D247443D07D04ADF0DA0D9412111134744E1E0107321ED5B9B29CC4C59DB744B59814AF3D891AF7217E403ED7" +
"34BA598DBE16994DED7EC74401DDF2D82C8C010F3ED4C4687AECD5977E60410EA89614E316CF26195A8336CD57B3026" +
"4471C54D5BA089A91EDC8321B16C2444CFE0F9385E6B2A37B7C758000E8114F7DB764B848A8250D9967E19EEBB8F909C62B2E2E1F1";


String decodedBinary = binaryCodec.decode(expected);
Payment deserialized = objectMapper.readValue(
decodedBinary,
objectMapper.getTypeFactory().constructType(Payment.class)
);

assertThat(multiSigPayment).isNotEqualTo(deserialized);

AddressCodec addressCodec = AddressCodec.getInstance();
assertThat(multiSigPayment.signers().stream().sorted(Comparator.comparing(
sign -> new BigInteger(addressCodec.decodeAccountId(
Address.of(sign.signer().account().value())
).hexValue(), 16)
)).collect(Collectors.toList()))
.isEqualTo(deserialized.signers());

}

@Test
public void submitMultisignedWithSignersInOrder() throws JsonProcessingException {

Payment unsignedPayment = Payment.builder()
.account(Address.of("rBcTTDopDWefBJoRHkLQ4SXcJ7jmERsB54"))
.fee(XrpCurrencyAmount.ofDrops(20))
.sequence(UnsignedInteger.ONE)
.amount(XrpCurrencyAmount.ofDrops(12345))
.destination(Address.of("rB7KywQ7ewYrCTZimJBH7VSegnt8KYyVze"))
.build();

List<SignerWrapper> signers = Lists.newArrayList(
SignerWrapper.of(Signer.builder()
.account(Address.of("rEzLrF8UtmrvgS8JjXvmUr1dEZnxVCicnJ"))
.signingPublicKey("EDB53FEFAB30FA2AD6EDB6EA3F5F9E4976CF765B94472933E1DAE3088F9707DDD7")
.transactionSignature("FAB3FA0C72F1FDAC99EA31701983F8F4F89803D6F7DF5465A22378EFE4ADA1C993B86B3" +
"226AAE3A239553F6DCF95CDED8E8FEBBC1C5343D3089A04C758353F03")
.build()
),
SignerWrapper.of(Signer.builder()
.account(Address.of("rPbYo1myPZq4JHbB7D587iR5rqBZ2L47J1"))
.signingPublicKey("ED5B9B29CC4C59DB744B59814AF3D891AF7217E403ED734BA598DBE16994DED7EC")
.transactionSignature("1DDF2D82C8C010F3ED4C4687AECD5977E60410EA89614E316CF26195A8336CD57B3026" +
"4471C54D5BA089A91EDC8321B16C2444CFE0F9385E6B2A37B7C758000E")
.build()
)
);

Payment multiSigPayment = Payment.builder()
.from(unsignedPayment)
.signers(signers)
.build();

String expected = "1200002280000000240000000161400000000000303968400000000000001481147465E5C80EA" +
"A9829630FB52A2DBE5F47FF7B95E9831472DC52A028EF1F8317D87794DEC6036A7292D502F3E0107321EDB53FEFAB30" +
"FA2AD6EDB6EA3F5F9E4976CF765B94472933E1DAE3088F9707DDD77440FAB3FA0C72F1FDAC99EA31701983F8F4F89803" +
"D6F7DF5465A22378EFE4ADA1C993B86B3226AAE3A239553F6DCF95CDED8E8FEBBC1C5343D3089A04C758353F038114" +
"A46957D247443D07D04ADF0DA0D9412111134744E1E0107321ED5B9B29CC4C59DB744B59814AF3D891AF7217E403ED7" +
"34BA598DBE16994DED7EC74401DDF2D82C8C010F3ED4C4687AECD5977E60410EA89614E316CF26195A8336CD57B3026" +
"4471C54D5BA089A91EDC8321B16C2444CFE0F9385E6B2A37B7C758000E8114F7DB764B848A8250D9967E19EEBB8F909C62B2E2E1F1";

assertSerializesAndDeserializes(multiSigPayment, expected);
}

private <T extends Transaction> void assertSerializesAndDeserializes(
T transaction,
String expectedBinary
Expand Down
Loading

0 comments on commit 56f267a

Please sign in to comment.