All Implemented Interfaces:
Serializable, DataStructure
Direct Known Subclasses:
LeaseSet, RouterInfo

public abstract class DatabaseEntryextends DataStructureImpl
Base class for data structures stored in the I2P network database (NetDb).

DatabaseEntry provides common infrastructure for NetDb-storable objects:

  • Core Types: Base for LeaseSet and RouterInfo
  • Unified Interface: Simplifies NetDB and I2NP implementation
  • Common Operations: Shared methods for hashing, routing, and signing
  • Integrity Protection: Prevents modification after signing

Key Features:

  • SHA-256 Hash: Unique identifier for database storage and lookup
  • Routing Key: Modified hash for distributed hash Table (DHT) routing
  • Timestamp: Creation or last-modified time for cache management
  • Signatures: Cryptographic signatures for authenticity verification
  • Type Constants: Standardized type identifiers for all NetDb entries

Supported Entry Types:

Integrity Protection:

  • Immutable After Signing: Objects cannot be modified once signed
  • IllegalStateException: Thrown when modification is attempted
  • NetDb Protection: Prevents corruption of network database
  • Message Safety: Protects I2NP messages from tampering

Usage Patterns:

  • Network Storage: Entries stored in distributed hash table
  • Lookup Operations: Fast retrieval by hash or routing key
  • Cache Management: Timestamp-based expiration and refresh
  • Floodfill: Distribution of new and updated entries

Security Considerations:

  • Signature Verification: Always verify before trusting entries
  • Timestamp Validation: Check for stale or expired entries
  • Hash Collision: Verify SHA-256 hash matches content
  • Routing Key Security: Protect against routing attacks

Implementation Notes:

  • 0.8.2: Initial implementation with retrofitting
  • Code Consolidation: Reduces instanceof usage throughout codebase
  • Thread Safety: Protection not guaranteed to be thread-safe
  • Object Reuse: Do not reuse DatabaseEntry instances

Warning:

  • Direct Modification: Avoid modifying internal byte[] objects
  • Corruption Avenues: Multiple paths can bypass protection
  • Careful Usage: Protection is not foolproof against all attacks
See Also:
  • Field Details

    • KEY_TYPE_ROUTERINFO

      public static final int KEY_TYPE_ROUTERINFO
      Router info type. These are the same as in i2np's DatabaseStoreMessage.
      See Also:
    • KEY_TYPE_LEASESET

      public static final int KEY_TYPE_LEASESET
      LeaseSet (v1) type.
      See Also:
    • KEY_TYPE_LS2

      public static final int KEY_TYPE_LS2
      LeaseSet 2 type.
      See Also:
    • KEY_TYPE_ENCRYPTED_LS2

      public static final int KEY_TYPE_ENCRYPTED_LS2
      Encrypted LeaseSet 2 type.
      See Also:
    • KEY_TYPE_META_LS2

      public static final int KEY_TYPE_META_LS2
      Meta LeaseSet 2 type.
      See Also:
    • KEY_TYPE_SERVICE_RECORD

      public static final int KEY_TYPE_SERVICE_RECORD
      Service record type.
      See Also:
    • KEY_TYPE_SERVICE_LIST

      public static final int KEY_TYPE_SERVICE_LIST
      Service list type.
      See Also:
    • _signature

      protected volatile Signature _signature
      Cryptographic signature.
    • _currentRoutingKey

      private Hash _currentRoutingKey
      Current routing key, cached. Synchronize on this object.
    • _routingKeyGenMod

      private long _routingKeyGenMod
      Routing key generation modifier, for cache invalidation.
    • _receivedAsPublished

      private volatile boolean _receivedAsPublished
      Whether this entry was received via a remote publish.
    • _receivedAsReply

      private volatile boolean _receivedAsReply
      Whether this entry was received as a reply to a search.
    • _receivedBy

      private Hash _receivedBy
      Hash of the client receiving the routerinfo, or null if it was sent directly.
  • Constructor Details

    • DatabaseEntry

      public DatabaseEntry()
      Constructor for NetDb entries; a subclass passes its entry type to the constructor that takes one.
  • Method Details

    • getReceivedBy

      public Hash getReceivedBy()
      The Hash of the local client that received this LS, null if the router or unknown.
      Returns:
      the hash of the receiving client, or null
    • setReceivedBy

      public void setReceivedBy(Hash receivedBy)
      Local client that received this entry.
      Parameters:
      receivedBy - the hash of the receiving client
    • getDate

      public abstract long getDate()
      A common interface to the timestamp of the two subclasses. Identical to getEarliestLeaseDate() in LeaseSet, and getPublished() in RouterInfo. Note that for a LeaseSet this will be in the future, and for a RouterInfo it will be in the past. Either way, it's a timestamp.
      Returns:
      the date this entry takes effect, in milliseconds since the epoch: the expiration of the earliest lease for a LeaseSet, the publication time for a RouterInfo
    • getKeysAndCert

      public abstract KeysAndCert getKeysAndCert()
      Keys and certificate for this entry. Identical to getDestination() in LeaseSet, and getIdentity() in RouterInfo.
      Returns:
      KAC or null
    • getHash

      public Hash getHash()
      A common interface to the Hash of the two subclasses. Identical to getDestination().calculateHash() in LeaseSet, and getIdentity().getHash() in RouterInfo.
      Returns:
      Hash or null
    • getType

      public abstract int getType()
      Type of the data structure. This should be faster than instanceof.
      Returns:
      KEY_TYPE_ROUTERINFO or KEY_TYPE_LEASESET or LS2 types
    • isLeaseSet

      public boolean isLeaseSet()
      Convenience method, is the type any variant of leaseset?
      Returns:
      true for any type of LeaseSet, false for RouterInfo, false for others
    • isLeaseSet

      public static boolean isLeaseSet(int type)
      Convenience method, is the type any variant of leaseset?
      Parameters:
      type - one of the DatabaseEntry key type constants
      Returns:
      true for any type of LeaseSet, false for RouterInfo, false for others
    • isRouterInfo

      public boolean isRouterInfo()
      Convenience method, is the type any variant of router info?
      Returns:
      true for any type of RouterInfo, false for LeaseSet, false for others
    • getBytes

      protected abstract byte[] getBytes() throws DataFormatException
      Returns the raw payload data, excluding the signature, to be signed by sign(SigningPrivateKey).

      Most callers should use writeBytes() or toByteArray() instead.

      Returns:
      the raw payload data, or null on error (for example, if this is a RouterInfo, a DataFormatException is thrown instead)
      Throws:
      DataFormatException - if the data cannot be serialized
    • getRoutingKey

      public Hash getRoutingKey()
      Routing key for the structure using the current modifier in the RoutingKeyGenerator. This only calculates a new one when necessary though (if the generator's key modifier changes).
      Returns:
      the routing key
      Throws:
      IllegalStateException - if not in RouterContext
    • validateRoutingKey

      public boolean validateRoutingKey()
      Validates the routing key for this entry.
      Returns:
      true if the routing key is valid
      Throws:
      IllegalStateException - if not in RouterContext
    • getSignature

      public Signature getSignature()
      Retrieve the proof that the identity stands behind the info here.
      Returns:
      the signature, or null if not signed
    • setSignature

      public void setSignature(Signature signature)
      Configure the proof that the entity stands behind the info here.
      Parameters:
      signature - the signature to set
      Throws:
      IllegalStateException - if already signed
    • sign

      public void sign(SigningPrivateKey key) throws DataFormatException
      Sign the structure using the supplied signing key.
      Parameters:
      key - the signing private key
      Throws:
      IllegalStateException - if already signed
      DataFormatException - if signing fails
    • getSigningPublicKey

      protected SigningPublicKey getSigningPublicKey()
      Identical to getDestination().getSigningPublicKey() in LeaseSet, and getIdentity().getSigningPublicKey() in RouterInfo.
      Returns:
      SPK or null
    • verifySignature

      public boolean verifySignature()
      This is the same as isValid() in RouterInfo or verifySignature() in LeaseSet.
      Returns:
      true if the entry carries a signature that verifies over its own data
    • getReceivedAsPublished

      public boolean getReceivedAsPublished()
      If true, we received this LeaseSet by a remote peer publishing it to us, rather than by searching for it ourselves or locally creating it. Default false.
      Returns:
      true if received as published
    • setReceivedAsPublished

      public void setReceivedAsPublished()
      Marks this entry as received via published mode. Use this carefully, when updating the flag make sure the old and new leaseSet are actually equivalent, or simply copy the reply value, as copyStoreMetadata() in KademliaNetworkDatabaseFacade does.
    • getReceivedAsReply

      public boolean getReceivedAsReply()
      If true, we received this LeaseSet by searching for it Default false.
      Returns:
      true if received as reply
    • setReceivedAsReply

      public void setReceivedAsReply()
      Marks this entry as received via reply.