mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-13 02:35:52 +00:00
Store states in protobufs instead of using Java Serialization.
Saves having to use reflection.
This commit is contained in:
parent
4b4405b7bc
commit
c98badcf1c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,7 @@ import com.google.bitcoin.core.*;
|
|||||||
import com.google.bitcoin.utils.Threading;
|
import com.google.bitcoin.utils.Threading;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.collect.HashMultimap;
|
import com.google.common.collect.HashMultimap;
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
import net.jcip.annotations.GuardedBy;
|
import net.jcip.annotations.GuardedBy;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
@ -157,14 +158,22 @@ public class StoredPaymentChannelClientStates implements WalletExtension {
|
|||||||
public byte[] serializeWalletExtension() {
|
public byte[] serializeWalletExtension() {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ClientState.StoredClientPaymentChannels.Builder builder = ClientState.StoredClientPaymentChannels.newBuilder();
|
||||||
ObjectOutputStream oos = new ObjectOutputStream(out);
|
|
||||||
for (StoredClientChannel channel : mapChannels.values()) {
|
for (StoredClientChannel channel : mapChannels.values()) {
|
||||||
oos.writeObject(channel);
|
// First a few asserts to make sure things won't break
|
||||||
|
checkState(channel.valueToMe.compareTo(BigInteger.ZERO) >= 0 && channel.valueToMe.compareTo(NetworkParameters.MAX_MONEY) < 0);
|
||||||
|
checkState(channel.refundFees.compareTo(BigInteger.ZERO) >= 0 && channel.refundFees.compareTo(NetworkParameters.MAX_MONEY) < 0);
|
||||||
|
checkNotNull(channel.myKey.getPrivKeyBytes());
|
||||||
|
checkState(channel.refund.getConfidence().getSource() == TransactionConfidence.Source.SELF);
|
||||||
|
builder.addChannels(ClientState.StoredClientPaymentChannel.newBuilder()
|
||||||
|
.setId(ByteString.copyFrom(channel.id.getBytes()))
|
||||||
|
.setContractTransaction(ByteString.copyFrom(channel.contract.bitcoinSerialize()))
|
||||||
|
.setRefundTransaction(ByteString.copyFrom(channel.refund.bitcoinSerialize()))
|
||||||
|
.setMyKey(ByteString.copyFrom(channel.myKey.getPrivKeyBytes()))
|
||||||
|
.setValueToMe(channel.valueToMe.longValue())
|
||||||
|
.setRefundFees(channel.refundFees.longValue()));
|
||||||
}
|
}
|
||||||
return out.toByteArray();
|
return builder.build().toByteArray();
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
@ -176,10 +185,17 @@ public class StoredPaymentChannelClientStates implements WalletExtension {
|
|||||||
try {
|
try {
|
||||||
checkState(this.containingWallet == null || this.containingWallet == containingWallet);
|
checkState(this.containingWallet == null || this.containingWallet == containingWallet);
|
||||||
this.containingWallet = containingWallet;
|
this.containingWallet = containingWallet;
|
||||||
ByteArrayInputStream inStream = new ByteArrayInputStream(data);
|
NetworkParameters params = containingWallet.getParams();
|
||||||
ObjectInputStream ois = new ObjectInputStream(inStream);
|
ClientState.StoredClientPaymentChannels states = ClientState.StoredClientPaymentChannels.parseFrom(data);
|
||||||
while (inStream.available() > 0) {
|
for (ClientState.StoredClientPaymentChannel storedState : states.getChannelsList()) {
|
||||||
StoredClientChannel channel = (StoredClientChannel)ois.readObject();
|
Transaction refundTransaction = new Transaction(params, storedState.getRefundTransaction().toByteArray());
|
||||||
|
refundTransaction.getConfidence().setSource(TransactionConfidence.Source.SELF);
|
||||||
|
StoredClientChannel channel = new StoredClientChannel(new Sha256Hash(storedState.getId().toByteArray()),
|
||||||
|
new Transaction(params, storedState.getContractTransaction().toByteArray()),
|
||||||
|
refundTransaction,
|
||||||
|
new ECKey(storedState.getMyKey().toByteArray(), null),
|
||||||
|
BigInteger.valueOf(storedState.getValueToMe()),
|
||||||
|
BigInteger.valueOf(storedState.getRefundFees()));
|
||||||
putChannel(channel, false);
|
putChannel(channel, false);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@ -193,14 +209,14 @@ public class StoredPaymentChannelClientStates implements WalletExtension {
|
|||||||
* channel which was interrupted (eg on connection failure) or keep track of refund transactions which need broadcast
|
* channel which was interrupted (eg on connection failure) or keep track of refund transactions which need broadcast
|
||||||
* when they expire.
|
* when they expire.
|
||||||
*/
|
*/
|
||||||
class StoredClientChannel implements Serializable {
|
class StoredClientChannel {
|
||||||
Sha256Hash id;
|
Sha256Hash id;
|
||||||
Transaction contract, refund;
|
Transaction contract, refund;
|
||||||
ECKey myKey;
|
ECKey myKey;
|
||||||
BigInteger valueToMe, refundFees;
|
BigInteger valueToMe, refundFees;
|
||||||
|
|
||||||
// In-memory flag to indicate intent to resume this channel (or that the channel is already in use)
|
// In-memory flag to indicate intent to resume this channel (or that the channel is already in use)
|
||||||
transient boolean active = false;
|
boolean active = false;
|
||||||
|
|
||||||
StoredClientChannel(Sha256Hash id, Transaction contract, Transaction refund, ECKey myKey, BigInteger valueToMe, BigInteger refundFees) {
|
StoredClientChannel(Sha256Hash id, Transaction contract, Transaction refund, ECKey myKey, BigInteger valueToMe, BigInteger refundFees) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
@ -17,16 +17,19 @@
|
|||||||
package com.google.bitcoin.protocols.channels;
|
package com.google.bitcoin.protocols.channels;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import com.google.bitcoin.core.*;
|
import com.google.bitcoin.core.*;
|
||||||
import com.google.bitcoin.utils.Threading;
|
import com.google.bitcoin.utils.Threading;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
import net.jcip.annotations.GuardedBy;
|
import net.jcip.annotations.GuardedBy;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keeps track of a set of {@link StoredServerChannel}s and expires them 2 hours before their refund transactions
|
* Keeps track of a set of {@link StoredServerChannel}s and expires them 2 hours before their refund transactions
|
||||||
@ -142,14 +145,23 @@ public class StoredPaymentChannelServerStates implements WalletExtension {
|
|||||||
public byte[] serializeWalletExtension() {
|
public byte[] serializeWalletExtension() {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ServerState.StoredServerPaymentChannels.Builder builder = ServerState.StoredServerPaymentChannels.newBuilder();
|
||||||
ObjectOutputStream oos = new ObjectOutputStream(out);
|
|
||||||
for (StoredServerChannel channel : mapChannels.values()) {
|
for (StoredServerChannel channel : mapChannels.values()) {
|
||||||
oos.writeObject(channel);
|
// First a few asserts to make sure things won't break
|
||||||
|
checkState(channel.bestValueToMe.compareTo(BigInteger.ZERO) >= 0 && channel.bestValueToMe.compareTo(NetworkParameters.MAX_MONEY) < 0);
|
||||||
|
checkState(channel.refundTransactionUnlockTimeSecs > 0);
|
||||||
|
checkNotNull(channel.myKey.getPrivKeyBytes());
|
||||||
|
ServerState.StoredServerPaymentChannel.Builder channelBuilder = ServerState.StoredServerPaymentChannel.newBuilder()
|
||||||
|
.setBestValueToMe(channel.bestValueToMe.longValue())
|
||||||
|
.setRefundTransactionUnlockTimeSecs(channel.refundTransactionUnlockTimeSecs)
|
||||||
|
.setContractTransaction(ByteString.copyFrom(channel.contract.bitcoinSerialize()))
|
||||||
|
.setClientOutput(ByteString.copyFrom(channel.clientOutput.bitcoinSerialize()))
|
||||||
|
.setMyKey(ByteString.copyFrom(channel.myKey.getPrivKeyBytes()));
|
||||||
|
if (channel.bestValueSignature != null)
|
||||||
|
channelBuilder.setBestValueSignature(ByteString.copyFrom(channel.bestValueSignature));
|
||||||
|
builder.addChannels(channelBuilder);
|
||||||
}
|
}
|
||||||
return out.toByteArray();
|
return builder.build().toByteArray();
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
@ -160,10 +172,16 @@ public class StoredPaymentChannelServerStates implements WalletExtension {
|
|||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
checkArgument(containingWallet == wallet);
|
checkArgument(containingWallet == wallet);
|
||||||
ByteArrayInputStream inStream = new ByteArrayInputStream(data);
|
ServerState.StoredServerPaymentChannels states = ServerState.StoredServerPaymentChannels.parseFrom(data);
|
||||||
ObjectInputStream ois = new ObjectInputStream(inStream);
|
NetworkParameters params = containingWallet.getParams();
|
||||||
while (inStream.available() > 0) {
|
for (ServerState.StoredServerPaymentChannel storedState : states.getChannelsList()) {
|
||||||
StoredServerChannel channel = (StoredServerChannel)ois.readObject();
|
StoredServerChannel channel = new StoredServerChannel(null,
|
||||||
|
new Transaction(params, storedState.getContractTransaction().toByteArray()),
|
||||||
|
new TransactionOutput(params, null, storedState.getClientOutput().toByteArray(), 0),
|
||||||
|
storedState.getRefundTransactionUnlockTimeSecs(),
|
||||||
|
new ECKey(storedState.getMyKey().toByteArray(), null),
|
||||||
|
BigInteger.valueOf(storedState.getBestValueToMe()),
|
||||||
|
storedState.hasBestValueSignature() ? storedState.getBestValueSignature().toByteArray() : null);
|
||||||
putChannel(channel);
|
putChannel(channel);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -28,7 +28,7 @@ import static com.google.common.base.Preconditions.checkArgument;
|
|||||||
* channel which was interrupted (eg on connection failure) or close the channel automatically as the channel expire
|
* channel which was interrupted (eg on connection failure) or close the channel automatically as the channel expire
|
||||||
* time approaches.
|
* time approaches.
|
||||||
*/
|
*/
|
||||||
public class StoredServerChannel implements Serializable {
|
public class StoredServerChannel {
|
||||||
BigInteger bestValueToMe;
|
BigInteger bestValueToMe;
|
||||||
byte[] bestValueSignature;
|
byte[] bestValueSignature;
|
||||||
long refundTransactionUnlockTimeSecs;
|
long refundTransactionUnlockTimeSecs;
|
||||||
@ -38,8 +38,8 @@ public class StoredServerChannel implements Serializable {
|
|||||||
|
|
||||||
// In-memory pointer to the event handler which handles this channel if the client is connected.
|
// In-memory pointer to the event handler which handles this channel if the client is connected.
|
||||||
// Used as a flag to prevent duplicate connections and to disconnect the channel if its expire time approaches.
|
// Used as a flag to prevent duplicate connections and to disconnect the channel if its expire time approaches.
|
||||||
transient PaymentChannelServer connectedHandler = null;
|
PaymentChannelServer connectedHandler = null;
|
||||||
transient PaymentChannelServerState state = null;
|
PaymentChannelServerState state = null;
|
||||||
|
|
||||||
StoredServerChannel(PaymentChannelServerState state, Transaction contract, TransactionOutput clientOutput,
|
StoredServerChannel(PaymentChannelServerState state, Transaction contract, TransactionOutput clientOutput,
|
||||||
long refundTransactionUnlockTimeSecs, ECKey myKey, BigInteger bestValueToMe, byte[] bestValueSignature) {
|
long refundTransactionUnlockTimeSecs, ECKey myKey, BigInteger bestValueToMe, byte[] bestValueSignature) {
|
||||||
|
45
core/src/storedclientpaymentchannel.proto
Normal file
45
core/src/storedclientpaymentchannel.proto
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/** Copyright 2013 Google Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Authors: Mike Hearn, Matt Corallo
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Notes:
|
||||||
|
* - Endianness: All byte arrays that represent numbers (such as hashes and private keys) are Big Endian
|
||||||
|
* - To regenerate after editing, run mvn clean package -DupdateProtobuf
|
||||||
|
*/
|
||||||
|
|
||||||
|
package paymentchannels;
|
||||||
|
|
||||||
|
option java_package = "com.google.bitcoin.protocols.channels";
|
||||||
|
option java_outer_classname = "ClientState";
|
||||||
|
|
||||||
|
|
||||||
|
// A set of StoredPaymentChannel's
|
||||||
|
message StoredClientPaymentChannels {
|
||||||
|
repeated StoredClientPaymentChannel channels = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A client-side payment channel in serialized form, which can be reloaded later if the client restarts and wants to
|
||||||
|
// reopen an existing channel
|
||||||
|
message StoredClientPaymentChannel {
|
||||||
|
required bytes id = 1;
|
||||||
|
required bytes contractTransaction = 2;
|
||||||
|
required bytes refundTransaction = 3;
|
||||||
|
required bytes myKey = 4;
|
||||||
|
required uint64 valueToMe = 5;
|
||||||
|
required uint64 refundFees = 6;
|
||||||
|
}
|
44
core/src/storedserverpaymentchannel.proto
Normal file
44
core/src/storedserverpaymentchannel.proto
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/** Copyright 2013 Google Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Authors: Mike Hearn, Matt Corallo
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Notes:
|
||||||
|
* - Endianness: All byte arrays that represent numbers (such as hashes and private keys) are Big Endian
|
||||||
|
* - To regenerate after editing, run mvn clean package -DupdateProtobuf
|
||||||
|
*/
|
||||||
|
|
||||||
|
package paymentchannels;
|
||||||
|
|
||||||
|
option java_package = "com.google.bitcoin.protocols.channels";
|
||||||
|
option java_outer_classname = "ServerState";
|
||||||
|
|
||||||
|
|
||||||
|
// A set of StoredPaymentChannel's
|
||||||
|
message StoredServerPaymentChannels {
|
||||||
|
repeated StoredServerPaymentChannel channels = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A server-side payment channel in serialized form, which can be reloaded later if the server restarts
|
||||||
|
message StoredServerPaymentChannel {
|
||||||
|
required uint64 bestValueToMe = 1;
|
||||||
|
optional bytes bestValueSignature = 2;
|
||||||
|
required uint64 refundTransactionUnlockTimeSecs = 3;
|
||||||
|
required bytes contractTransaction = 4;
|
||||||
|
required bytes clientOutput = 5;
|
||||||
|
required bytes myKey = 6;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user