Skip to content

Releases: Layr-Labs/eigensdk-rs

v1.0.0-rc.0 - mainnet slashing

11 Apr 21:26
609324e
Compare
Choose a tag to compare
Pre-release

What's Changed

Added 🎉

  • Bump alloy to 0.13 and MSRV to 1.81 in PR 419.

  • Bump middleware to v1.3.0 in PR 443.

  • Added an additional implementation for OperatorInfoService for retrieving operator BLS pubkeys and sockets directly from middleware in #414. The new OperatorInfoOnChain is more stable and efficient since it doesn't subscribe or fetch events, but it requires functionality from the recent v1.3.0 middleware release.

    Old Implementation which indexes middleware events:

      use eigen_services_operatorsinfo::{operatorsinfo_inmemory::OperatorInfoServiceInMemory};
      let operators_info = OperatorInfoServiceInMemory::new(
          get_test_logger(),
          avs_registry_reader.clone(),
          ws_endpoint,
      )
      .await
      .unwrap()
      .0;
    
      let cancellation_token = CancellationToken::new();
      let operators_info_clone = operators_info.clone();
      let token_clone = cancellation_token.clone();
      task::spawn(async move { operators_info_clone.start_service(&token_clone, start_block, end_block).await });
      // Sleep to wait for the operator info service to start
      sleep(Duration::from_secs(1)).await;
    
      let avs_registry_service =
          AvsRegistryServiceChainCaller::new(avs_registry_reader.clone(), operators_info);

    New alternate implementation which directly queries from middleware using view call:

      use eigen_services_operatorsinfo::{operatorsinfo_inmemory::OperatorInfoOnChain};
      let operators_info_on_chain = OperatorInfoOnChain::new(
          &http_endpoint,
          bls_apk_registry_address,
          socket_registry_address,
      );
    
      let avs_registry_service = AvsRegistryServiceChainCaller::new(
          avs_registry_reader.clone(),
          operators_info_on_chain,
      );
    
      let pub_keys = operator_info_on_chain
          .get_operator_info(OPERATOR_ADDRESS)
          .await
          .unwrap();
      
      let socket = operator_info_on_chain
          .get_operator_socket(OPERATOR_ADDRESS)
          .await
          .unwrap();

Breaking Changes 🛠

  • Changing NodeApi to allow concurrent modifications of the internal state of the node in PR 401.

    Before: NodeApi had the function create_server to start the Node API. Now, there are two functions NodeApi::new and NodeApi::start_server to create the server and then start it.

    Also, users can now call functions to modify the information served dynamically by interacting with the NodeApi methods. As an end-to-end example:

      let mut node_info = NodeInfo::new("test_node", "v1.0.0");
      node_info.register_service(
          "test_service",
          "Test Service",
          "Test service description",
          ServiceStatus::Up,
      );
    
      // Set up a server running on a test address (e.g., 127.0.0.1:8081)
      let ip_port_addr = "127.0.0.1:8081";
    
      let mut node_api = NodeApi::new(node_info);
      let server = node_api.start_server(ip_port_addr).unwrap();
    
      // and then you can dinamically modify the state of the node:
      node_api
          .update_service_status("test_service", ServiceStatus::Down)
          .unwrap();

Documentation 📚

Other Changes

  • Moved test utils from chainio folder to testing/testutils folder by @maximopalopoli in #407

  • Added rewards utilities integration test by @maximopalopoli in #404

  • test: check quorum creation after service initialization is working by @MegaRedHand in #400

  • chore: use common testing utils in bls_agg_test in PR #420.

  • chore: remove unused dependency in eigen-cli by @MegaRedHand in #421

  • test: wait for transaction before doing call by @MegaRedHand in #422

  • chore: merge changes from main branch by @MegaRedHand in #446

  • Fixed release workflow. We now use release-plz for releases.

Full Changelog: v0.5.0...v1.0.0-rc.0

v0.5.0-testnet-holesky

18 Mar 22:06
339617c
Compare
Choose a tag to compare
Pre-release

What's Changed

Added 🎉

  • Added all features of the eigensdk crate to its "full" feature #370

    • This includes: "types", "utils", "metrics-collectors-economic", and "metrics-collectors-rpc-calls" features.
  • Bump alloy to 0.12 in #381.

  • Added register_for_operator_sets_with_churn method to elcontracts/writer in #382.

      let el_chain_writer_2 =
          new_test_writer(http_endpoint.clone(), SECOND_PRIVATE_KEY.to_string()).await;
    
      let bls_key_pair = BlsKeyPair::new(OPERATOR_BLS_KEY_2.to_string()).unwrap();
      let churn_private_key = FIRST_PRIVATE_KEY.to_string();
      let churn_sig_salt = FixedBytes::from([0x05; 32]);
      let churn_sig_expiry = U256::MAX;
      
      let tx_hash = el_chain_writer_2
          .register_for_operator_sets_with_churn(
              SECOND_ADDRESS,         // Operator address to register
              bls_key_pair,           // Operator's BLS key pair
              avs_address,            // AVS address
              vec![operator_set_id],  // Operator set ID
              "socket".to_string(),   // Socket address
              Bytes::from([0]),       // Quorum numbers
              vec![FIRST_ADDRESS],    // Operators to kick if quorum is full
              churn_private_key,      // Churn approver's private key
              churn_sig_salt,         // Churn signature salt
              churn_sig_expiry,       // Churn signature expiry
          )
          .await
          .unwrap();

Breaking Changes 🛠

  • Renamed set_account_identifier to set_avs #365

  • Changed the signature of build_avs_registry_chain_writer in #384.

    • The operator_state_retriever_addr parameter was replaced by service_manager_addr.
    • This change was made because later middleware versions do not include ServiceManager.
    // Before
    pub async fn build_avs_registry_chain_writer(
        logger: SharedLogger,
        provider: String,
        signer: String,
        registry_coordinator_addr: Address,
        _operator_state_retriever_addr: Address,
    ) -> Result<Self, AvsRegistryError> {}
    
    // After
    pub async fn build_avs_registry_chain_writer(
        logger: SharedLogger,
        provider: String,
        signer: String,
        registry_coordinator_addr: Address,
        service_manager_addr: Address,
    ) -> Result<Self, AvsRegistryError> {}
  • Bump middleware to v1.4.0-testnet-holesky in [#396] , [#365], [#395] and [#388].

    • Added method is_operator_slashable.
  let chain_reader = build_el_chain_reader(http_endpoint.clone()).await;

  let operator_set = OperatorSet {
      id: 1,
      avs: Address::ZERO,
  };

  let is_slashable = chain_reader
      .is_operator_slashable(OPERATOR_ADDRESS, operator_set)
      .await
      .unwrap();
  assert!(!is_slashable);
  • Added method get_allocated_stake.
  let chain_reader = build_el_chain_reader(http_endpoint.clone()).await;

  let operator_set = OperatorSet {
      id: 1,
      avs: Address::ZERO,
  };
  let operators = vec![OPERATOR_ADDRESS];
  let strategies = vec![get_erc20_mock_strategy(http_endpoint.to_string()).await];
  let slashable_stake = chain_reader
      .get_allocated_stake(operator_set, operators, strategies)
      .await
      .unwrap();
  • Added method get_encumbered_magnitude.
  let chain_reader = build_el_chain_reader(http_endpoint.clone()).await;

  let magnitude = chain_reader
      .get_encumbered_magnitude(
          OPERATOR_ADDRESS,
          get_erc20_mock_strategy(http_endpoint.to_string()).await,
      )
      .await
      .unwrap();
  • Updated error types in BlsAggregationServiceError for channel failures in the BLS Aggregator Service (#392).
    • Before: A generic ChannelError was used for both sender and receiver channel failures.
    • After: Distinct errors are now provided:
      • SenderError is returned when the sender channel fails to send a message to the service.
      • ReceiverError is returned when the receiver channel fails to receive a message from the service.

Removed 🗑

  • Removed unused empty structs from the library in #371
    • eigen_client_eth::client::Client
    • eigen_services_operatorsinfo::OperatorPubKeysService
  • Removed the AvsRegistryChainReader::is_operator_set_quorum method #365

Documentation 📚

  • Reflect 2 bindings(rewardsv2 and slashing) in readme in #383.

Other Changes

New Contributors

Full Changelog: v0.4.0-rc.1...v0.5.0

v0.4.0-rc.1 - Slashing

20 Feb 20:09
565a48a
Compare
Choose a tag to compare
Pre-release

⚠️ Important

Previously, we maintained one state across the SDK, with this release we now maintain two bindings:-

  • RewardsV2 - Current mainnet release.
  • Slashing - Middleware's dev branch latest commit.

Previously we use to import this way

use eigen_utils::middleware::*;

Newer way to import bindings

use eigen_utils::rewardsv2::middleware::*;
use eigen_utils::slashing::middleware::*;

What's Changed

Added 🎉

  • Implemented create_avs_rewards_submission #345

      let rewards_submissions = vec![RewardsSubmission {
          strategiesAndMultipliers: strategies_and_multipliers,
          token,
          amount: U256::from(1_000),
          startTimestamp: last_valid_interval_start,
          duration: rewards_duration,
      }];
    
      let tx_hash = avs_writer
          .create_avs_rewards_submission(rewards_submissions)
          .await
          .unwrap();
  • Added new method update_avs_metadata_uri in avsregistry/writer in #344.

      let tx_hash = avs_writer
          .update_avs_metadata_uri(new_metadata)
          .await
          .unwrap();
  • Added new method register_operator_with_churn in avsregistry/writer in #354.

      let bls_key_pair = BlsKeyPair::new(BLS_KEY).unwrap();
      let operator_sig_salt = FixedBytes::from([0x02; 32]); 
      let operator_sig_expiry = U256::MAX;
      let quorum_nums = Bytes::from([0]);
      let socket = "socket".to_string();
      let churn_sig_salt = FixedBytes::from([0x05; 32]);
      let churn_sig_expiry = U256::MAX;
    
    
      let tx_hash = avs_writer_2
          .register_operator_with_churn(
              bls_key_pair,                 // Operator's BLS key pair
              operator_sig_salt,            // Operator signature salt
              operator_sig_expiry,          // Operator signature expiry
              quorum_nums,                  // Quorum numbers for registration
              socket,                       // Socket address
              vec![REGISTERED_OPERATOR],    // Operators to kick if quorum is full
              CHURN_PRIVATE_KEY,            // Churn approver's private key
              churn_sig_salt,               // Churn signature salt
              churn_sig_expiry,             // Churn signature expiry
          )
          .await
          .unwrap();
  • Added new method set_churn_approver in avsregistry/writer in #333.

    let tx_hash = avs_writer
        .set_churn_approver(new_churn_approver_address)
        .await
        .unwrap();
  • Added new method set_signer in ELChainWriter and AvsRegistryChainWriter in #364.

    avs_registry_chain_writer.set_signer(PRIVATE_KEY_STRING);
    el_chain_writer.set_signer(PRIVATE_KEY_STRING);
  • Added additional method register_as_operator_preslashing in ELChainWriter in #366. This method is to be used for pre-slashing operator registration.

     let operator = Operator {
              address: ADDRESS, 
              delegation_approver_address: ADDRESS,
              metadata_url: "metadata_uri".to_string(),
              allocation_delay: None,
              _deprecated_earnings_receiver_address: None,
              staker_opt_out_window_blocks: Some(0u32),
          };
      el_chain_writer
          .register_as_operator_preslashing(operator)
          .await
          .unwrap();

Breaking Changes 🛠

  • TaskMetadata.task_created_block field changed to u64 #362

  • Refactor bls_aggr module in #363.

    • Separated the interface and service in the bls_aggr module.
      • To interact with the BLS aggregation service, use the ServiceHandle struct. Aggregation responses are now handled by the AggregateReceiver struct.
        • To initialize both structs, use the BLSAggregationService::start method. It returns a tuple with the ServiceHandle and AggregateReceiver structs.
      • Add methods start and run to BLSAggregationService struct.
    • Removed initialize_new_task and process_new_signature functions since their logic is now integrated in run().
    // Before
    let bls_agg_service = BlsAggregatorService::new(avs_registry_service, get_test_logger());
    let metadata = TaskMetadata::new(
          task_index,
          block_number,
          quorum_numbers,
          quorum_threshold_percentages,
          time_to_expiry,
      );
      
      bls_agg_service.initialize_new_task(metadata).await.unwrap();
    
      bls_agg_service
          .process_new_signature(TaskSignature::new(
              task_index,
              task_response_digest,
              bls_signature,
              test_operator_1.operator_id,
          ))
          .await
          .unwrap();
    
    // After
    let bls_agg_service = BlsAggregatorService::new(avs_registry_service, get_test_logger());
    let (handle, mut aggregator_response) = bls_agg_service.start();
    
    let metadata = TaskMetadata::new(
        task_index,
        block_number,
        quorum_numbers,
        quorum_threshold_percentages,
        time_to_expiry,
    );
    handle.initialize_task(metadata).await.unwrap();
    
    handle
        .process_signature(TaskSignature::new(
            task_index,
            task_response_digest,
            bls_signature,
            test_operator_1.operator_id,
        ))
        .await
        .unwrap();

Removed 🗑

  • Removed eigen-testing-utils dependency from eigen-cli crate in #353.
  • Modifications to eigen-testing-utils in #357.
    • Removed mine_anvil_blocks_operator_set from eigen-testing-utils. Users should use mine_anvil_blocks that does the same thing.
    • Removed the third parameter of set_account_balance. Now the port used is the default used on start_anvil_container and start_m2_anvil_container.

Other Changes

New Contributors

Full Changelog: v0.3.0...v0.4.0-rc.1

v0.3.0 - Rewards 2.1 testnet

11 Feb 21:02
4cf1969
Compare
Choose a tag to compare

What's Changed

Added🎉

  • Added new method set_slashable_stake_lookahead in avsregistry/writer in #278.

      let quorum_number = 0_u8;
      let lookahead = 10_u32;
      let tx_hash = avs_writer
          .set_slashable_stake_lookahead(quorum_number, lookahead)
          .await
          .unwrap();
  • Added new method set_rewards_initiator in avsregistry/writer in #273.

      let tx_hash = avs_writer
        .set_rewards_initiator(new_rewards_init_address)
        .await
        .unwrap();
  • Added new method clear_deallocation_queue in elcontracts/writer in #270

    let tx_hash_clear = el_chain_writer
        .clear_deallocation_queue(
            operator_address,
            vec![strategy_addr],
            vec![num_to_clear],
        )
        .await
        .unwrap();
  • Added update_socket function for avs registry writer in #268
    An example of use is the following:

    // Given an avs writer and a new socket address:
    
    let tx_hash = avs_writer
      .update_socket(new_socket_addr.into())
      .await
      .unwrap();
    
    let tx_status = wait_transaction(&http_endpoint, tx_hash)
      .await
      .unwrap()
      .status(); 
    // tx_status should be true
  • Added Rewards2.1 support in #323.

    • Set an operator's split on an operator set.
        let operator_set = OperatorSet {
              avs: avs_address,
              id: 0,
          };
    
          let new_split = 5;
          let tx_hash = el_chain_writer
              .set_operator_set_split(OPERATOR_ADDRESS, operator_set.clone(), new_split)
              .await
              .unwrap();
    • Get an operator's split on an operator set.
       let operator_set = OperatorSet {
              avs: avs_address,
              id: 0,
          };
         let split = el_chain_writer
              .el_chain_reader
              .get_operator_set_split(OPERATOR_ADDRESS, operator_set)
              .await
              .unwrap(); 
  • Added new method set_operator_set_param in avsregistry/writer in #327.

     let operator_set_params = OperatorSetParam {
          maxOperatorCount: 10,
          kickBIPsOfOperatorStake: 50,
          kickBIPsOfTotalStake: 50,
      };
    
      let tx_hash = avs_writer
          .set_operator_set_param(0, operator_set_params.clone())
          .await
          .unwrap();
  • Added new method eject_operator in avsregistry/writer in #328.

      let register_operator_address = address!("f39Fd6e51aad88F6F4ce6aB8827279cffFb92266");
      let quorum_nums = Bytes::from([0]);
    
      let tx_hash = avs_writer
          .eject_operator(register_operator_address, quorum_nums)
          .await
          .unwrap();
  • Added new method is_operator_set_quorum in avsregistry/writer in #296.

      let operator_set_quourm = avs_reader.is_operator_set_quorum(0).await.unwrap();
  • Added version explicitly in crates in #322.

  • Added new method set_account_identifier in avsregistry/writer in #329.

      let tx_hash = avs_writer
          .set_account_identifier(new_identifier_address)
          .await
          .unwrap();

Changed

Breaking changes🛠

  • refactor: update interface on bls aggregation in #254
    • Introduces a new struct TaskMetadata with a constructor TaskMetadata::new to initialize a new task and a method with_window_duration to set the window duration.

    • Refactors initialize_new_task and single_task_aggregator to accept a TaskMetadata struct instead of multiple parameters.

      // BEFORE
      bls_agg_service
            .initialize_new_task(
                task_index,
                block_number as u32,
                quorum_numbers,
                quorum_threshold_percentages,
                time_to_expiry,
            )
            .await
            .unwrap();
      
      // AFTER
      let metadata = TaskMetadata::new(
              task_index,
              block_number,
              quorum_numbers,
              quorum_threshold_percentages,
              time_to_expiry,
        )
      bls_agg_service.initialize_new_task(metadata).await.unwrap();
    • Removes initialize_new_task_with_window since window_duration can now be set in TaskMetadata.

      // BEFORE
      bls_agg_service
            .initialize_new_task_with_window(
                task_index,
                block_number as u32,
                quorum_numbers,
                quorum_threshold_percentages,
                time_to_expiry,
                window_duration,
            )
            .await
            .unwrap();
      
      // AFTER
      let metadata = TaskMetadata::new(
              task_index,
              block_number,
              quorum_numbers,
              quorum_threshold_percentages,
              time_to_expiry,
          ).with_window_duration(window_duration);
      bls_agg_service.initialize_new_task(metadata).await.unwrap();
  • refactor: encapsulate parameters into TaskSignature in #260
    • Introduced TaskSignature struct to encapsulate parameters related to task signatures:
    • Updated process_new_signature to accept a TaskSignature struct instead of multiple parameters.
      // BEFORE
      bls_agg_service.process_new_signature(task_index, task_response_digest, bls_signature, operator_id).await.unwrap();
      
      // AFTER
      let task_signature = TaskSignature::new(
            task_index,
            task_response_digest,
            bls_signature,
            operator_id,
      );
      bls_agg_service.process_new_signature(task_signature).await.unwrap();
  • Slashing UAM changes in #248.

Removed

Other Changes

New Contributors

Full Changelog: v0.1.3...v0.3.0

v0.2.0

06 Feb 17:37
a53e4c0
Compare
Choose a tag to compare

What's Changed

Security 🔒

  • chore(deps): bump openssl from 0.10.68 to 0.10.70 in the cargo group across 1 directory by @dependabot in #291

Added 🎉

  • Added eigen_common dependency to the eigensdk crate when "full" feature is enabled in #249.

    • Now when enabling the "full" feature:

      eigensdk = { version = "0.2", features = ["full"] }

      You can use access the eigen-common crate as a submodule of eigensdk:

      use eigensdk::common::*;
  • Added bindings for ECDSAStakeRegistry and ECDSAServiceManagerBase in #269.

    • These bindings can be accessed from:

      // From `eigensdk`
      use eigensdk::utils::middleware::ecdsaservicemanagerbase;
      use eigensdk::utils::middleware::ecdsastakeregistry;
      // From `eigen_utils`
      use eigen_utils::middleware::ecdsaservicemanagerbase;
      use eigen_utils::middleware::ecdsastakeregistry;
  • Starting on this release, we're using release-plz to streamline our release process.

    • Added release-plz in ci in #275.
    • Added custom configuration for release-plz in #281.
    • Fixed typo in release-plz toml file in #284.

Breaking Changes 🛠

  • fix: use rewards coordinator on get operator avs/pi split methods by @maximopalopoli in #250

    • The parameters of ChainReader::new changed, and it now receives the address of the rewards coordinator.

      It was previously called this way:

      let el_chain_reader = ELChainReader::new(
          logger,
          SLASHER_ADDRESS,
          DELEGATION_MANAGER_ADDRESS,
          AVS_DIRECTORY_ADDRESS,
          provider_url,
      );

      Now, it's called this way:

      let el_chain_reader = ELChainReader::new(
          logger,
          SLASHER_ADDRESS,
          DELEGATION_MANAGER_ADDRESS,
          REWARDS_COORDINATOR,
          AVS_DIRECTORY_ADDRESS,
          provider_url,
      );

Removed 🗑

  • Removed homepage from testing-utils crate in #266.
  • Removed changelog generation by release-plz in #281.
  • Removed examples packages from workspace.dependencies in Cargo.toml in #287.
  • Removed release-plz-pr workflow in release-plz in #292.

Documentation 📚

  • Fixed the rewardsv2 bindings version in readme to 0.5.4 in #246.
  • docs: improve changelog by adding examples by @maximopalopoli in #251

Other Changes

  • Changes in the way bindings are generated in #243.
    • The bindings target now generates the bindings using Docker with Foundry v0.3.0.
    • The previous bindings target was renamed to bindings_host, as it runs without Docker. However the bindings_host target is for CI use only. To generate the bindings, please use the bindings target.
  • Fixed incorrect package name in Cargo.toml for examples in #285.
  • docs: add mention of updated bindings to changelog by @MegaRedHand in #233
  • chore: format contracts by @ricomateo in #235
  • ci: add foundry workflow by @ricomateo in #236
  • ci: add CI job to check whether anvil state is up to date by @ricomateo in #237
  • chore: remove existing bindings when generating new ones by @ricomateo in #242
  • chore: remove alloy reexported crates from dependencies by @ricomateo in #244
  • docs: sync root and crates/eigensdk/ READMEs by @ricomateo in #245
  • ci: add workflow to enforce updates to the changelog by @ricomateo in #239
  • docs: add RELEASE.md by @MegaRedHand in #231
  • ci: fix check bindings job by @pablodeymo in #247
  • ci: fix job that checks anvil state is up-to-date by @ricomateo in #252
  • refactor: move bindings generation to script by @MegaRedHand in #271
  • fix: simplify Cargo.toml by @MegaRedHand in #282
  • ci: split tests and coverage by @MegaRedHand in #286

New Contributors

Full Changelog: v0.1.3...v0.2.0

v0.1.3 - mainnet-rewards-v2

17 Jan 19:13
f39b87a
Compare
Choose a tag to compare

What's Changed

Added 🎉

  • feat: add rewards-v2 related functionality by @supernovahs in #221
    • New methods in ELChainReader:
      • get_operator_avs_split
      • get_operator_pi_split
    • New methods in ELChainWriter:
      • set_operator_avs_split
      • set_operator_pi_split
    • Bindings updated for rewards-v2 core contracts release

Breaking Changes 🛠

  • feat!: remove delegation manager from ELChainWriter by @supernovahs in #214
    • ELChainWriter::new no longer receives the delegation manager address as first parameter.
  • feat!: change way bindings are generated by @MegaRedHand in #204
    • eigen_utils::core contains bindings related to core contracts
    • eigen_utils::middleware contains bindings related to middleware contracts
    • eigen_utils::sdk contains bindings related to the SDK (should only be used for testing)

Documentation 📚

Other Changes

New Contributors

Full Changelog: v0.1.2...v0.1.3

v0.1.2 - mainnet-rewards

09 Jan 21:33
1dc8366
Compare
Choose a tag to compare

What's Changed

Full Changelog: v0.1.1...v0.1.2

v0.1.1

29 Nov 21:17
c91ab11
Compare
Choose a tag to compare
v0.1.1 Pre-release
Pre-release

Notable change

The most notable change in this release is the addition of a BLS Aggregation window waiting period after quorum is reached.

What's Changed

New Contributors

Full Changelog: v0.1.0...v0.1.1

eigensdk-rs v0.1.0

30 Sep 14:01
2733f62
Compare
Choose a tag to compare

Summary

This is our first release 🎉. The SDK has achieved full feature parity with the Go SDK.

Main features are:-

  • chainio: Interact with the eigenlayer contracts along with AVS contracts.
  • bls: Signing, verifying, alloy utilities for bn254 curve using arkworks.
  • eigen-cli: Supports keystore generation for ECDSA and BLS(compatible with EIP 2333,2334,2335)
  • metrics: Eigenlayer metrics implementation
  • nodeapi: Eigenlayer nodeapi implementation
  • services: Get operators info, aggregate bls signatures , get operators avs state
  • signer: aws signer, web3 signer,keystore signer and private key signer.
  • testing-utils: Contains publicly exportable addresses of eigenlayer contract, middleware contracts for holesky, mainnet and anvil utilities.
  • example : Examples demonstrating the use of SDK.
  • logging: Utility to get logger, noop_logger (for testing).

What's Changed