Skip to content

Commit

Permalink
Update to ConsensusJ 0.7.0-alpha2
Browse files Browse the repository at this point in the history
TODO:

* Add SSLContext constructors to OmniClient, etc.
* Figure out what to do about DefaultAddressParserProvider being
package private.
* Rewrite or remove (mostly unused) OmniTransaction and OmniTransactionParser
* Look for and fix other deprecations
  • Loading branch information
msgilligan committed Aug 31, 2023
1 parent 79d51a7 commit 28d6435
Show file tree
Hide file tree
Showing 22 changed files with 223 additions and 54 deletions.
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ omnijVersion = 0.7.0-SNAPSHOT

useMavenLocal = false

bitcoinjVersion = 0.17-alpha1
consensusjVersion = 0.7.0-alpha1
bitcoinjVersion = 0.17-alpha2
consensusjVersion = 0.7.0-alpha2
slf4jVersion = 2.0.7
groovyVersion = 4.0.13
spockVersion = 2.3-groovy-4.0
Expand Down
2 changes: 1 addition & 1 deletion gradle/javadoc.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ ext.javadocSpec = {
"https://fasterxml.github.io/jackson-databind/javadoc/2.13/"
]

if (!bitcoinjVersion.contains("beta") && !bitcoinjVersion.contains("rc")) {
if (!bitcoinjVersion.contains("alpha") && !bitcoinjVersion.contains("beta") && !bitcoinjVersion.contains("rc")) {
javaDocLinks.add("https://bitcoinj.org/javadoc/${bitcoinjVersion}/".toString())
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import foundation.omni.rpc.OmniClient;
import org.consensusj.bitcoin.cli.BitcoinCLITool;

import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.SSLContext;
import java.io.PrintStream;
import java.io.PrintWriter;

Expand All @@ -21,7 +21,7 @@ public OmniCoreCLICall(BitcoinCLITool tool, PrintStream out, PrintStream err, St
}

@Override
public OmniClient createClient(SSLSocketFactory sslSocketFactory, RpcConfig config) {
return new OmniClient(sslSocketFactory, config.network(), config.getURI(), config.getUsername(), config.getPassword(), false, false);
public OmniClient createClient(SSLContext sslContext, RpcConfig config) {
return new OmniClient(sslContext.getSocketFactory(), config.network(), config.getURI(), config.getUsername(), config.getPassword(), false, false);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
* Copyright by the original author or authors.
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package foundation.omni.address;

import org.bitcoinj.base.Address;
import org.bitcoinj.base.AddressParser;
import org.bitcoinj.base.Base58;
import org.bitcoinj.base.Bech32;
import org.bitcoinj.base.BitcoinNetwork;
import org.bitcoinj.base.LegacyAddress;
import org.bitcoinj.base.Network;
import org.bitcoinj.base.SegwitAddress;
import org.bitcoinj.base.exceptions.AddressFormatException;
import org.bitcoinj.base.internal.StreamUtils;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.params.Networks;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
* Copied from bitcoinj because in 0.17-alpha2 the class is package private.
* Address parser that knows about the address types supported by bitcoinj core and is configurable
* with additional network types.
*/
public class DefaultAddressParserProvider implements AddressParser.AddressParserProvider {

// Networks to try when parsing segwit addresses
static final List<Network> DEFAULT_NETWORKS_SEGWIT = unmodifiableList(
BitcoinNetwork.MAINNET,
BitcoinNetwork.TESTNET,
BitcoinNetwork.REGTEST);

// Networks to try when parsing legacy (base58) addresses
static final List<Network> DEFAULT_NETWORKS_LEGACY = unmodifiableList(
BitcoinNetwork.MAINNET,
BitcoinNetwork.TESTNET);

// Networks to search when parsing segwit addresses
private final List<Network> segwitNetworks;
// Networks to search when parsing base58 addresses
private final List<Network> base58Networks;

/**
* DefaultAddressParser with default network lists
*/
DefaultAddressParserProvider() {
this(DEFAULT_NETWORKS_SEGWIT, DEFAULT_NETWORKS_LEGACY);
}

/**
* Use this constructor if you have a custom list of networks to use when parsing addresses
* @param segwitNetworks Networks to search when parsing segwit addresses
* @param base58Networks Networks to search when parsing base58 addresses
*/
public DefaultAddressParserProvider(List<Network> segwitNetworks, List<Network> base58Networks) {
this.segwitNetworks = segwitNetworks;
this.base58Networks = base58Networks;
}

@Override
public AddressParser forKnownNetworks() {
return this::parseAddress;
}

@Override
public AddressParser forNetwork(Network network) {
return address -> this.parseAddress(address, network);
}

/**
* Dynamically create a new AddressParser using a snapshot of currently configured networks
* from Networks.get().
* @return A backward-compatible parser
*/
static DefaultAddressParserProvider fromNetworks() {
List<Network> nets = Networks.get().stream()
.map(NetworkParameters::network)
.collect(StreamUtils.toUnmodifiableList());
return new DefaultAddressParserProvider(nets, nets);
}

private Address parseAddress(String addressString) throws AddressFormatException {
try {
return parseBase58AnyNetwork(addressString);
} catch (AddressFormatException.WrongNetwork x) {
throw x;
} catch (AddressFormatException x) {
try {
return parseBech32AnyNetwork(addressString);
} catch (AddressFormatException.WrongNetwork x2) {
throw x;
} catch (AddressFormatException x2) {
//throw new AddressFormatException(addressString);
throw x2;
}
}
}

private Address parseAddress(String addressString, Network network) throws AddressFormatException {
try {
return LegacyAddress.fromBase58(addressString, network);
} catch (AddressFormatException.WrongNetwork x) {
throw x;
} catch (AddressFormatException x) {
try {
return SegwitAddress.fromBech32(addressString, network);
} catch (AddressFormatException.WrongNetwork x2) {
throw x;
} catch (AddressFormatException x2) {
throw new AddressFormatException(addressString);
}
}
}

/**
* Construct a {@link SegwitAddress} from its textual form.
*
* @param bech32 bech32-encoded textual form of the address
* @return constructed address
* @throws AddressFormatException if something about the given bech32 address isn't right
*/
private SegwitAddress parseBech32AnyNetwork(String bech32)
throws AddressFormatException {
String hrp = Bech32.decode(bech32).hrp;
return segwitNetworks.stream()
.filter(n -> hrp.equals(n.segwitAddressHrp()))
.findFirst()
.map(n -> SegwitAddress.fromBech32(bech32, n))
.orElseThrow(() -> new AddressFormatException.InvalidPrefix("No network found for " + bech32));
}

/**
* Construct a {@link LegacyAddress} from its base58 form.
*
* @param base58 base58-encoded textual form of the address
* @throws AddressFormatException if the given base58 doesn't parse or the checksum is invalid
* @throws AddressFormatException.WrongNetwork if the given address is valid but for a different chain (eg testnet vs mainnet)
*/
private LegacyAddress parseBase58AnyNetwork(String base58)
throws AddressFormatException, AddressFormatException.WrongNetwork {
int version = Base58.decodeChecked(base58)[0] & 0xFF;
return base58Networks.stream()
.filter(n -> version == n.legacyAddressHeader() || version == n.legacyP2SHHeader())
.findFirst()
.map(n -> LegacyAddress.fromBase58(base58, n))
.orElseThrow(() -> new AddressFormatException.InvalidPrefix("No network found for " + base58));
}

// Create an unmodifiable set of NetworkParameters from an array/varargs
private static List<Network> unmodifiableList(Network... ts) {
return Collections.unmodifiableList(new ArrayList<>(Arrays.asList(ts)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@ public static SegwitAddress btcToOmni(SegwitAddress btcAddress) {
OmniNetwork omniNet = btcNetworkToOmniNetwork((BitcoinNetwork) btcAddress.network());
Bech32.Bech32Data btcBech32Data = Bech32.decode(btcAddress.toBech32());
String omniAddressString = Bech32.encode(Bech32.Encoding.BECH32, omniNet.segwitAddressHrp(), btcBech32Data.data);
return (SegwitAddress) OmniNetwork.addressParser.parseAddress(omniAddressString, omniNet);
return (SegwitAddress) OmniNetwork.addressParser.forNetwork(omniNet).parseAddress(omniAddressString);
}

public static SegwitAddress btcToOmni(String btcAddressString) {
SegwitAddress btcAddress = (SegwitAddress) OmniNetwork.addressParser.parseAddressAnyNetwork(btcAddressString);
SegwitAddress btcAddress = (SegwitAddress) OmniNetwork.addressParser.forKnownNetworks().parseAddress(btcAddressString);
return btcToOmni(btcAddress);
}

public static SegwitAddress omniToBtc(SegwitAddress omniAddress) {
BitcoinNetwork btcNet = omniNetworkToBtcNetwork((OmniNetwork) omniAddress.network());
Bech32.Bech32Data btcBech32Data = Bech32.decode(omniAddress.toBech32());
String btcAddressString = Bech32.encode(Bech32.Encoding.BECH32, btcNet.segwitAddressHrp(), btcBech32Data.data);
return (SegwitAddress) OmniNetwork.addressParser.parseAddress(btcAddressString, btcNet);
return (SegwitAddress) OmniNetwork.addressParser.forNetwork(btcNet).parseAddress(btcAddressString);
}

public static SegwitAddress omniToBtc(String omniAddressString) {
SegwitAddress omniAddress = (SegwitAddress) OmniNetwork.addressParser.parseAddressAnyNetwork(omniAddressString);
SegwitAddress omniAddress = (SegwitAddress) OmniNetwork.addressParser.forKnownNetworks().parseAddress(omniAddressString);
return omniToBtc(omniAddress);
}

Expand Down
6 changes: 3 additions & 3 deletions omnij-core/src/main/java/foundation/omni/net/OmniNetwork.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package foundation.omni.net;

import foundation.omni.address.DefaultAddressParserProvider;
import org.bitcoinj.base.Address;
import org.bitcoinj.base.AddressParser;
import org.bitcoinj.base.BitcoinNetwork;
import org.bitcoinj.base.Coin;
import org.bitcoinj.base.DefaultAddressParser;
import org.bitcoinj.base.LegacyAddress;
import org.bitcoinj.base.Monetary;
import org.bitcoinj.base.Network;
Expand Down Expand Up @@ -37,9 +37,9 @@ public enum OmniNetwork implements Network {
* Scheme part for Bitcoin URIs.
*/
public static final String BITCOIN_SCHEME = "bitcoin";
public static final AddressParser addressParser;
public static final AddressParser.AddressParserProvider addressParser;
static {
addressParser = new DefaultAddressParser(List.of(BitcoinNetwork.MAINNET, BitcoinNetwork.TESTNET, OmniNetwork.MAINNET, OmniNetwork.TESTNET),
addressParser = new DefaultAddressParserProvider(List.of(BitcoinNetwork.MAINNET, BitcoinNetwork.TESTNET, OmniNetwork.MAINNET, OmniNetwork.TESTNET),
List.of(BitcoinNetwork.MAINNET, BitcoinNetwork.TESTNET, OmniNetwork.MAINNET, OmniNetwork.TESTNET));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public ClassCEncoder(Network network) {
* @return A bitcoinj {@code Transaction} object
*/
public Transaction encode(Address refAddress, byte[] payload) {
Transaction txClassC = new Transaction(netParams);
Transaction txClassC = new Transaction();

TransactionOutput output = encodeOpReturnOutput(payload);
txClassC.addOutput(output);
Expand All @@ -58,7 +58,7 @@ public Transaction encode(Address refAddress, byte[] payload) {
public TransactionOutput encodeOpReturnOutput(byte[] payload) {
Script script = createOmniTxOpReturnScript(payload);

return new TransactionOutput(netParams, null, Coin.ZERO, script.getProgram());
return new TransactionOutput(null, Coin.ZERO, script.getProgram());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ public Transaction encode(ECKey redeemingKey, byte[] data) {
keysByOutput.add(group);
}

Transaction txClassB = new Transaction(NetworkParameters.of(network));
Transaction txClassB = new Transaction();

for (List<ECKey> group : keysByOutput) {
// Add the redeemable key to the front of each group list
List<ECKey> redeemableGroup = new ArrayList<>();
redeemableGroup.add(redeemingKey);
redeemableGroup.addAll(group);
Script script = ScriptBuilder.createMultiSigOutputScript(1, redeemableGroup); // 1 of redeemableGroup.size() multisig
TransactionOutput output = new TransactionOutput(NetworkParameters.of(network), null, Coin.ZERO, script.getProgram());
TransactionOutput output = new TransactionOutput(null, Coin.ZERO, script.getProgram());
output.setValue(calcNonDustValue(output));
txClassB.addOutput(output);
}
Expand Down
16 changes: 10 additions & 6 deletions omnij-core/src/main/java/foundation/omni/tx/OmniTransaction.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package foundation.omni.tx;

import org.bitcoinj.base.Address;
import org.bitcoinj.base.BitcoinNetwork;
import org.bitcoinj.base.ScriptType;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.crypto.ECKey;
Expand All @@ -15,8 +16,10 @@

/**
* Omni Protocol transaction
*
* TODO: Omni Transaction class should not be a subclass of
* @deprecated This code is incomplete, doesn't work, and will be replaced.
*/
@Deprecated
public class OmniTransaction extends Transaction {
//Address fromAddress;
//Address refAddress;
Expand All @@ -25,14 +28,14 @@ public class OmniTransaction extends Transaction {

/* Create from Bitcoin transaction */
public OmniTransaction(Transaction transaction) {
super(transaction.getParams(), ByteBuffer.wrap(transaction.bitcoinSerialize())); // Is serialized byte array == payload byte array???
super(); // Is serialized byte array == payload byte array???

// For now assume only a single multisig encoded output
// Also Assume it is a simple send
List<ECKey> keys = null;
List<TransactionOutput> outputs = transaction.getOutputs();
for (TransactionOutput output : outputs) {
Script script = new Script(output.getScriptBytes());
Script script = Script.parse(output.getScriptBytes());
if (ScriptPattern.isSentToMultisig(script)) {
keys = script.getPubKeys();
}
Expand All @@ -55,7 +58,8 @@ public OmniTransaction(Transaction transaction) {
ECKey redeemKey = keys.get(0);
ECKey dataKey = keys.get(1); // 0th key is redeem key, 1st key contains data

Address redeemAddress = redeemKey.toAddress(ScriptType.P2PKH, transaction.getParams().network());
// TODO: Fix hard-coded Network
Address redeemAddress = redeemKey.toAddress(ScriptType.P2PKH, BitcoinNetwork.MAINNET);

byte[] input = dataKey.getPubKey();
byte[] deobf = Obfuscation.obfuscate(input, redeemAddress);
Expand All @@ -71,13 +75,13 @@ public OmniTransaction(Transaction transaction) {

/* Create unsigned */
public OmniTransaction(ECKey redeemingKey, Address refAddress, byte[] payload) throws InsufficientMoneyException {
super(NetworkParameters.of(refAddress.network()));
super();
throw new RuntimeException("Not implemented yet");
}

/* Create Signed */
public OmniTransaction(ECKey fromKey, List<TransactionOutput> unspentOutputs, Address refAddress, byte[] payload) throws InsufficientMoneyException {
super(NetworkParameters.of(refAddress.network()));
super();
throw new RuntimeException("Not implemented yet");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
import org.bitcoinj.core.Transaction;

/**
*
* @deprecated This code is incomplete, doesn't work, and will be replaced.
*/
@Deprecated
public class OmniTransactionParser {

OmniTransaction parse(Transaction btcTx) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ class OmniSegwitAddressConverterSpec extends Specification {
}

static SegwitAddress fromBech32(String addressString) {
(SegwitAddress) OmniNetwork.addressParser.parseAddressAnyNetwork(addressString)
(SegwitAddress) OmniNetwork.addressParser.forKnownNetworks().parseAddress(addressString)
}

void setupSpec() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ class BitcoinJTransactionBuilderSpec extends BaseTxSpec {
tx.addOutput(Coin.MILLICOIN, omniParams.exodusAddress)
tx.addOutput(Coin.CENT, toAddress)
Script script = ScriptBuilder.createInputScript(null)
def outPoint = new TransactionOutPoint(NetworkParameters.of(network), 1, Sha256Hash.of("boppitybop".getBytes()))
def outPoint = new TransactionOutPoint(1, Sha256Hash.of("boppitybop".getBytes()))

TransactionInput input = new TransactionInput(NetworkParameters.of(network), null, script.program, outPoint, null)
TransactionInput input = new TransactionInput(null, script.program, outPoint, null)
tx.addInput(input)
byte[] rawTx = tx.bitcoinSerialize()

Expand Down
Loading

0 comments on commit 28d6435

Please sign in to comment.