syntax = "proto3";

package gossip.v1;

option go_package = "github.com/certusone/wormhole/node/pkg/proto/gossip/v1;gossipv1";

message GossipMessage {
  oneof message {
    SignedObservation signed_observation = 2;
    SignedHeartbeat signed_heartbeat = 3;
    SignedVAAWithQuorum signed_vaa_with_quorum = 4;
    SignedObservationRequest signed_observation_request = 5;
  }
}

message SignedHeartbeat {
  // Serialized Heartbeat message.
  bytes heartbeat = 1;

  // ECDSA signature using the node's guardian public key.
  bytes signature = 2;

  // Guardian address that signed this payload (truncated Eth address).
  // This is already contained in Heartbeat, however, we want to verify
  // the payload before we deserialize it.
  bytes guardian_addr = 3;
}

// P2P gossip heartbeats for network introspection purposes.
message Heartbeat {
  // The node's arbitrarily chosen, untrusted nodeName.
  string node_name = 1;
  // A monotonic counter that resets to zero on startup.
  int64 counter = 2;
  // UNIX wall time.
  int64 timestamp = 3;

  message Network {
    // Canonical chain ID.
    uint32 id = 1;
    // Consensus height of the node.
    int64 height = 2;
    // Chain-specific human-readable representation of the bridge contract address.
    string contract_address = 3;
    // Connection error count
    uint64 error_count = 4;
  }
  repeated Network networks = 4;

  // Human-readable representation of the current bridge node release.
  string version = 5;

  // Human-readable representation of the guardian key's address.
  string guardian_addr = 6;

  // UNIX boot timestamp.
  int64 boot_timestamp = 7;
}

// A SignedObservation is a signed statement by a given guardian node
// that they observed a given event.
//
// Observations always result from an external, final event being observed.
// Examples are emitted messages in finalized blocks on a block or guardian set changes
// injected by node operators after reaching off-chain consensus.
//
// The event is uniquely identified by its hashed (tx_hash, nonce, values...) tuple.
//
// Other nodes will verify the signature. Once any node has observed a quorum of
// guardians submitting valid signatures for a given hash, they can be assembled into a VAA.
//
// Messages without valid signature are dropped unceremoniously.
message SignedObservation {
  // Guardian pubkey as truncated eth address.
  bytes addr = 1;
  // The observation's deterministic, unique hash.
  bytes hash = 2;
  // ECSDA signature of the hash using the node's guardian key.
  bytes signature = 3;
  // Transaction hash this observation was made from.
  // Optional, included for observability.
  bytes tx_hash = 4;
  // Message ID (chain/emitter/seq) for this observation.
  // Optional, included for observability.
  string message_id = 5;
}

// A SignedVAAWithQuorum message is sent by nodes whenever one of the VAAs they observed
// reached a 2/3+ quorum to be considered valid. Signed VAAs are broadcasted to the gossip
// network to allow nodes to persist them even if they failed to observe the signature.
message SignedVAAWithQuorum {
  bytes vaa = 1;
}

// Any guardian can send a SignedObservationRequest to the network to request
// all guardians to re-observe a given transaction. This is rate-limited to one
// request per second per guardian to prevent abuse.
//
// In the current implementation, this is only implemented for Solana.
// For Solana, the tx_hash is the account address of the transaction's message account.
message SignedObservationRequest {
  // Serialized observation request.
  bytes observation_request = 1;

  // Signature
  bytes signature = 2;
  bytes guardian_addr = 3;
}

message ObservationRequest {
  uint32 chain_id = 1;
  bytes tx_hash = 2;
}
