mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-01-19 05:33:44 +01:00
Wallet: migrate updateTime
field to java.time
API
This commit is contained in:
parent
85cc162642
commit
95549b4754
@ -50,6 +50,7 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@ -59,6 +60,7 @@ import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
@ -90,9 +92,9 @@ public class Transaction extends ChildMessage {
|
||||
* into the past.
|
||||
*/
|
||||
public static final Comparator<Transaction> SORT_TX_BY_UPDATE_TIME = (tx1, tx2) -> {
|
||||
final long time1 = tx1.getUpdateTime().getTime();
|
||||
final long time2 = tx2.getUpdateTime().getTime();
|
||||
final int updateTimeComparison = -(Long.compare(time1, time2));
|
||||
Instant t1 = tx1.getUpdateTimeInstant().orElse(Instant.EPOCH);
|
||||
Instant t2 = tx2.getUpdateTimeInstant().orElse(Instant.EPOCH);
|
||||
final int updateTimeComparison = -(t1.compareTo(t2));
|
||||
//If time1==time2, compare by tx hash to make comparator consistent with equals
|
||||
return updateTimeComparison != 0 ? updateTimeComparison : tx1.getTxId().compareTo(tx2.getTxId());
|
||||
};
|
||||
@ -146,7 +148,7 @@ public class Transaction extends ChildMessage {
|
||||
// block in which it was included. Note that this can be changed by re-orgs so the wallet may update this field.
|
||||
// Old serialized transactions don't have this field, thus null is valid. It is used for returning an ordered
|
||||
// list of transactions from a wallet, which is helpful for presenting to users.
|
||||
private Date updatedAt;
|
||||
@Nullable private Instant updateTime = null;
|
||||
|
||||
// These are in memory helpers only. They contain the transaction hashes without and with witness.
|
||||
private Sha256Hash cachedTxId;
|
||||
@ -402,9 +404,9 @@ public class Transaction extends ChildMessage {
|
||||
* @param relativityOffset A number that disambiguates the order of transactions within a block.
|
||||
*/
|
||||
public void setBlockAppearance(StoredBlock block, boolean bestChain, int relativityOffset) {
|
||||
long blockTime = block.getHeader().getTimeSeconds() * 1000;
|
||||
if (bestChain && (updatedAt == null || updatedAt.getTime() == 0 || updatedAt.getTime() > blockTime)) {
|
||||
updatedAt = new Date(blockTime);
|
||||
Instant blockTime = block.getHeader().getTimeInstant();
|
||||
if (bestChain && (updateTime == null || updateTime.equals(Instant.EPOCH) || updateTime.isAfter(blockTime))) {
|
||||
updateTime = blockTime;
|
||||
}
|
||||
|
||||
addBlockAppearance(block.getHeader().getHash(), relativityOffset);
|
||||
@ -520,18 +522,40 @@ public class Transaction extends ChildMessage {
|
||||
|
||||
/**
|
||||
* Returns the earliest time at which the transaction was seen (broadcast or included into the chain),
|
||||
* or the epoch if that information isn't available.
|
||||
* or empty if that information isn't available.
|
||||
*/
|
||||
public Date getUpdateTime() {
|
||||
if (updatedAt == null) {
|
||||
// Older wallets did not store this field. Set to the epoch.
|
||||
updatedAt = new Date(0);
|
||||
}
|
||||
return updatedAt;
|
||||
public Optional<Instant> getUpdateTimeInstant() {
|
||||
return Optional.ofNullable(updateTime);
|
||||
}
|
||||
|
||||
public void setUpdateTime(Date updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
/** @deprecated use {@link #getUpdateTimeInstant()} */
|
||||
@Deprecated
|
||||
public Date getUpdateTime() {
|
||||
return Date.from(getUpdateTimeInstant().orElse(Instant.EPOCH));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the update time of this transaction.
|
||||
* @param updateTime update time
|
||||
*/
|
||||
public void setUpdateTime(Instant updateTime) {
|
||||
this.updateTime = checkNotNull(updateTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the update time of this transaction.
|
||||
*/
|
||||
public void clearUpdateTime() {
|
||||
this.updateTime = null;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #setUpdateTime(Instant)} or {@link #clearUpdateTime()} */
|
||||
@Deprecated
|
||||
public void setUpdateTime(Date updateTime) {
|
||||
if (updateTime != null && updateTime.getTime() > 0)
|
||||
setUpdateTime(updateTime.toInstant());
|
||||
else
|
||||
clearUpdateTime();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -781,9 +805,8 @@ public class Transaction extends ChildMessage {
|
||||
* A human readable version of the transaction useful for debugging. The format is not guaranteed to be stable.
|
||||
* @param chain If provided, will be used to estimate lock times (if set). Can be null.
|
||||
*/
|
||||
public String toString(@Nullable AbstractBlockChain chain, @Nullable CharSequence indent) {
|
||||
if (indent == null)
|
||||
indent = "";
|
||||
public String toString(@Nullable AbstractBlockChain chain, @Nullable CharSequence nullableIndent) {
|
||||
final CharSequence indent = nullableIndent != null ? nullableIndent : "";
|
||||
StringBuilder s = new StringBuilder();
|
||||
Sha256Hash txId = getTxId(), wTxId = getWTxId();
|
||||
s.append(indent).append(txId);
|
||||
@ -797,8 +820,8 @@ public class Transaction extends ChildMessage {
|
||||
if (size != vsize)
|
||||
s.append(vsize).append(" virtual bytes, ");
|
||||
s.append(size).append(" bytes\n");
|
||||
if (updatedAt != null)
|
||||
s.append(indent).append("updated: ").append(TimeUtils.dateTimeFormat(updatedAt)).append('\n');
|
||||
getUpdateTimeInstant().ifPresent(
|
||||
time -> s.append(indent).append("updated: ").append(TimeUtils.dateTimeFormat(time.toEpochMilli())).append('\n'));
|
||||
if (version != 1)
|
||||
s.append(indent).append("version ").append(version).append('\n');
|
||||
|
||||
|
@ -2017,7 +2017,11 @@ public class Wallet extends BaseTaggableObject
|
||||
// two wallets depend on the same transaction.
|
||||
Transaction cloneTx = tx.getParams().getDefaultSerializer().makeTransaction(tx.bitcoinSerialize());
|
||||
cloneTx.setPurpose(tx.getPurpose());
|
||||
cloneTx.setUpdateTime(tx.getUpdateTime());
|
||||
Optional<Instant> updateTime = tx.getUpdateTimeInstant();
|
||||
if (updateTime.isPresent())
|
||||
cloneTx.setUpdateTime(updateTime.get());
|
||||
else
|
||||
cloneTx.clearUpdateTime();
|
||||
|
||||
riskDropped.put(cloneTx.getTxId(), cloneTx);
|
||||
log.warn("There are now {} risk dropped transactions being kept in memory", riskDropped.size());
|
||||
@ -2036,7 +2040,11 @@ public class Wallet extends BaseTaggableObject
|
||||
// two wallets depend on the same transaction.
|
||||
Transaction cloneTx = tx.getParams().getDefaultSerializer().makeTransaction(tx.bitcoinSerialize());
|
||||
cloneTx.setPurpose(tx.getPurpose());
|
||||
cloneTx.setUpdateTime(tx.getUpdateTime());
|
||||
Optional<Instant> updateTime = tx.getUpdateTimeInstant();
|
||||
if (updateTime.isPresent())
|
||||
cloneTx.setUpdateTime(updateTime.get());
|
||||
else
|
||||
cloneTx.clearUpdateTime();
|
||||
|
||||
// If this tx spends any of our unspent outputs, mark them as spent now, then add to the pending pool. This
|
||||
// ensures that if some other client that has our keys broadcasts a spend we stay in sync. Also updates the
|
||||
@ -2764,7 +2772,7 @@ public class Wallet extends BaseTaggableObject
|
||||
return false;
|
||||
log.info("commitTx of {}", tx.getTxId());
|
||||
Coin balance = getBalance();
|
||||
tx.setUpdateTime(TimeUtils.now());
|
||||
tx.setUpdateTime(TimeUtils.currentTime());
|
||||
// Put any outputs that are sending money back to us into the unspents map, and calculate their total value.
|
||||
Coin valueSentToMe = Coin.ZERO;
|
||||
for (TransactionOutput o : tx.getOutputs()) {
|
||||
|
@ -258,9 +258,8 @@ public class WalletProtobufSerializer {
|
||||
.setHash(hashToByteString(tx.getTxId()))
|
||||
.setVersion((int) tx.getVersion());
|
||||
|
||||
if (tx.getUpdateTime() != null) {
|
||||
txBuilder.setUpdatedAt(tx.getUpdateTime().getTime());
|
||||
}
|
||||
tx.getUpdateTimeInstant().ifPresent(
|
||||
time -> txBuilder.setUpdatedAt(time.toEpochMilli()));
|
||||
|
||||
if (tx.getLockTime() > 0) {
|
||||
txBuilder.setLockTime((int)tx.getLockTime());
|
||||
@ -628,7 +627,11 @@ public class WalletProtobufSerializer {
|
||||
tx.setVersion(txProto.getVersion());
|
||||
|
||||
if (txProto.hasUpdatedAt()) {
|
||||
tx.setUpdateTime(new Date(txProto.getUpdatedAt()));
|
||||
long updatedAt = txProto.getUpdatedAt();
|
||||
if (updatedAt > 0)
|
||||
tx.setUpdateTime(Instant.ofEpochMilli(updatedAt));
|
||||
else
|
||||
tx.clearUpdateTime();
|
||||
}
|
||||
|
||||
for (Protos.TransactionOutput outputProto : txProto.getTransactionOutputList()) {
|
||||
|
@ -1468,8 +1468,8 @@ public class WalletTest extends TestWithWallet {
|
||||
|
||||
// Verify we can handle the case of older wallets in which the timestamp is null (guessed from the
|
||||
// block appearances list).
|
||||
tx1.setUpdateTime(null);
|
||||
tx3.setUpdateTime(null);
|
||||
tx1.clearUpdateTime();
|
||||
tx3.clearUpdateTime();
|
||||
// Check we got them back in order.
|
||||
transactions = wallet.getTransactionsByTime();
|
||||
assertEquals(tx2, transactions.get(0));
|
||||
|
Loading…
Reference in New Issue
Block a user