package com.ripple.core.fields;
import java.util.*;
public enum Field {
// These are all presorted (verified in a static block below)
// They can then be used in a TreeMap, using the Enum (private) ordinal
// comparator
Generic(0, Type.Unknown),
Invalid(-1, Type.Unknown),
LedgerEntryType(1, Type.UInt16),
TransactionType(2, Type.UInt16),
Flags(2, Type.UInt32),
SourceTag(3, Type.UInt32),
Sequence(4, Type.UInt32),
PreviousTxnLgrSeq(5, Type.UInt32),
LedgerSequence(6, Type.UInt32),
CloseTime(7, Type.UInt32),
ParentCloseTime(8, Type.UInt32),
SigningTime(9, Type.UInt32),
Expiration(10, Type.UInt32),
TransferRate(11, Type.UInt32),
WalletSize(12, Type.UInt32),
OwnerCount(13, Type.UInt32),
DestinationTag(14, Type.UInt32),
HighQualityIn(16, Type.UInt32),
HighQualityOut(17, Type.UInt32),
LowQualityIn(18, Type.UInt32),
LowQualityOut(19, Type.UInt32),
QualityIn(20, Type.UInt32),
QualityOut(21, Type.UInt32),
StampEscrow(22, Type.UInt32),
BondAmount(23, Type.UInt32),
LoadFee(24, Type.UInt32),
OfferSequence(25, Type.UInt32),
FirstLedgerSequence(26, Type.UInt32), // Deprecated: do not use
// Added new semantics in 9486fc416ca7c59b8930b734266eed4d5b714c50
LastLedgerSequence(27, Type.UInt32),
TransactionIndex(28, Type.UInt32),
OperationLimit(29, Type.UInt32),
ReferenceFeeUnits(30, Type.UInt32),
ReserveBase(31, Type.UInt32),
ReserveIncrement(32, Type.UInt32),
SetFlag(33, Type.UInt32),
ClearFlag(34, Type.UInt32),
IndexNext(1, Type.UInt64),
IndexPrevious(2, Type.UInt64),
BookNode(3, Type.UInt64),
OwnerNode(4, Type.UInt64),
BaseFee(5, Type.UInt64),
ExchangeRate(6, Type.UInt64),
LowNode(7, Type.UInt64),
HighNode(8, Type.UInt64),
EmailHash(1, Type.Hash128),
LedgerHash(1, Type.Hash256),
ParentHash(2, Type.Hash256),
TransactionHash(3, Type.Hash256),
AccountHash(4, Type.Hash256),
PreviousTxnID(5, Type.Hash256),
LedgerIndex(6, Type.Hash256),
WalletLocator(7, Type.Hash256),
RootIndex(8, Type.Hash256),
// Added in rippled commit: 9486fc416ca7c59b8930b734266eed4d5b714c50
AccountTxnID(9, Type.Hash256),
BookDirectory(16, Type.Hash256),
InvoiceID(17, Type.Hash256),
Nickname(18, Type.Hash256),
Amendment(19, Type.Hash256),
TicketID(20, Type.Hash256),
hash(257, Type.Hash256),
index(258, Type.Hash256),
Amount(1, Type.Amount),
Balance(2, Type.Amount),
LimitAmount(3, Type.Amount),
TakerPays(4, Type.Amount),
TakerGets(5, Type.Amount),
LowLimit(6, Type.Amount),
HighLimit(7, Type.Amount),
Fee(8, Type.Amount),
SendMax(9, Type.Amount),
MinimumOffer(16, Type.Amount),
RippleEscrow(17, Type.Amount),
// Added in rippled commit: e7f0b8eca69dd47419eee7b82c8716b3aa5a9e39
DeliveredAmount(18, Type.Amount),
// These are auxillary fields
// quality(257, Type.AMOUNT),
taker_gets_funded(258, Type.Amount),
taker_pays_funded(259, Type.Amount),
PublicKey(1, Type.Blob),
MessageKey(2, Type.Blob),
SigningPubKey(3, Type.Blob),
TxnSignature(4, Type.Blob),
Generator(5, Type.Blob),
Signature(6, Type.Blob),
Domain(7, Type.Blob),
FundCode(8, Type.Blob),
RemoveCode(9, Type.Blob),
ExpireCode(10, Type.Blob),
CreateCode(11, Type.Blob),
MemoType(12, Type.Blob),
MemoData(13, Type.Blob),
MemoFormat(14, Type.Blob),
Account(1, Type.AccountID),
Owner(2, Type.AccountID),
Destination(3, Type.AccountID),
Issuer(4, Type.AccountID),
Target(7, Type.AccountID),
RegularKey(8, Type.AccountID),
ObjectEndMarker(1, Type.STObject),
TransactionMetaData(2, Type.STObject),
CreatedNode(3, Type.STObject),
DeletedNode(4, Type.STObject),
ModifiedNode(5, Type.STObject),
PreviousFields(6, Type.STObject),
FinalFields(7, Type.STObject),
NewFields(8, Type.STObject),
TemplateEntry(9, Type.STObject),
Memo(10, Type.STObject),
ArrayEndMarker(1, Type.STArray),
SigningAccounts(2, Type.STArray),
TxnSignatures(3, Type.STArray),
Signatures(4, Type.STArray),
Template(5, Type.STArray),
Necessary(6, Type.STArray),
Sufficient(7, Type.STArray),
AffectedNodes(8, Type.STArray),
Memos(9, Type.STArray),
CloseResolution(1, Type.UInt8),
TemplateEntryType(2, Type.UInt8),
TransactionResult(3, Type.UInt8),
TakerPaysCurrency(1, Type.Hash160),
TakerPaysIssuer(2, Type.Hash160),
TakerGetsCurrency(3, Type.Hash160),
TakerGetsIssuer(4, Type.Hash160),
Paths(1, Type.PathSet),
Indexes(1, Type.Vector256),
Hashes(2, Type.Vector256),
Features(3, Type.Vector256),
Transaction(1, Type.Transaction),
LedgerEntry(1, Type.LedgerEntry),
Validation(1, Type.Validation);
final int id;
// defaults
boolean signingField = true;
boolean isSerialized = true;
boolean isVlEncoded = false;
public static Field fromString(String key) {
Field f;
try {
f = valueOf(key);
} catch (IllegalArgumentException e) {
f = null;
}
return f;
}
public static byte[] asBytes(Field field) {
int name = field.getId(), type = field.getType().getId();
ArrayList<Byte> header = new ArrayList<Byte>(3);
if (type < 16)
{
if (name < 16) // common type, common name
header.add((byte)((type << 4) | name));
else
{
// common type, uncommon name
header.add((byte)(type << 4));
header.add((byte)(name));
}
}
else if (name < 16)
{
// uncommon type, common name
header.add((byte)(name));
header.add((byte)(type));
}
else
{
// uncommon type, uncommon name
header.add((byte)(0));
header.add((byte)(type));
header.add((byte)(name));
}
byte[] headerBytes = new byte[header.size()];
for (int i = 0; i < header.size(); i++) {
headerBytes[i] = header.get(i);
}
return headerBytes;
}
public int getId() {
return id;
}
final int code;
final Type type;
private final byte[] bytes;
public Object tag = null;
Field(int fid, Type tid) {
id = fid;
type = tid;
code = (type.id << 16) | fid;
if (isSerialized()) {
bytes = asBytes(this);
} else {
bytes = null;
}
isSerialized = isSerialized(this);
}
static private HashMap<Integer, Field> byCode = new HashMap<Integer, Field>();
public static Iterator<Field> sorted(Collection<Field> fields) {
ArrayList<Field> fieldList = new ArrayList<Field>(fields);
Collections.sort(fieldList, comparator);
return fieldList.iterator();
}
static public Field fromCode(Integer integer) {
return byCode.get(integer);
}
public Type getType() {
return type;
}
public boolean isSerialized() {
return isSerialized;
}
public boolean isVLEncoded() {
return isVlEncoded;
}
public boolean isSigningField() {
return signingField;
}
private static boolean isSerialized(Field f) {
// This should screen out `hash` and `index` and the like
return ((f.type.id > 0) && (f.type.id < 256) && (f.id > 0) && (f.id < 256));
}
static public Comparator<Field> comparator = new Comparator<Field>() {
@Override
public int compare(Field o1, Field o2) {
return o1.code - o2.code;
}
};
static {
for (Field f : Field.values()) {
byCode.put(f.code, f);
f.isSerialized = isSerialized(f);
f.signingField = f.isSerialized;
switch (f.type) {
case Blob:
case AccountID:
case Vector256:
f.isVlEncoded = true;
break;
default:
break;
}
}
TxnSignature.signingField = false;
ArrayList<Field> sortedFields;
Field[] values = Field.values();
sortedFields = new ArrayList<Field>(Arrays.asList(values));
Collections.sort(sortedFields, comparator);
for (int i = 0; i < values.length; i++) {
Field av = values[i];
Field lv = sortedFields.get(i);
if (av.code != lv.code) {
throw new RuntimeException("Field enum declaration isn't presorted");
}
}
}
public byte[] getBytes() {
return bytes;
}
}