Giter Site home page Giter Site logo

blinklabs-io / gouroboros Goto Github PK

View Code? Open in Web Editor NEW
61.0 1.0 10.0 1.18 MB

Go implementation of the Cardano Ouroboros protocol

License: Apache License 2.0

Makefile 0.13% Go 99.66% Python 0.20%
cardano golang go network protocol ouroboros ouroboros-network library blockchain golang-library

gouroboros's Introduction

gOurobros Logo
GitHub Go Reference Discord

Introduction

gOuroboros is a powerful and versatile framework for building Go apps that interact with the Cardano blockchain. Quickly and easily write Go apps that communicate with Cardano nodes or manage blocks/transactions. Sync the blockchain from a local or remote node, query a local node for protocol parameters or UTxOs by address, and much more.

Features

This is not an exhaustive list of existing and planned features, but it covers the bulk of it.

  • Ouroboros support
    • Muxer
      • support for multiple mini-protocols over single connection
      • support for separate initiator and responder instance for each protocol
      • support for buffer limits for each mini-protocol
    • Protocols
      • Handshake
        • Client support
        • Server support
      • Keepalive
        • Client support
        • Server support
      • ChainSync
        • Client support
        • Server support
      • BlockFetch
        • Client support
        • Server support
      • TxSubmission
        • Client support
        • Server support
      • PeerSharing
        • Client support
        • Server support
      • LocalTxSubmission
        • Client support
        • Server support
      • LocalTxMonitor
        • Client support
        • Server support
      • LocalStateQuery
        • Client support
        • Server support
        • Queries
          • System start
          • Current era
          • Chain tip
          • Era history
          • Current protocol parameters
          • Stake distribution
          • Non-myopic member rewards
          • Proposed protocol parameter updates
          • UTxOs by address
          • UTxO whole
          • UTxO by TxIn
          • Debug epoch state
          • Filtered delegations and reward accounts
          • Genesis config
          • Reward provenance
          • Stake pools
          • Stake pool params
          • Reward info pools
          • Pool state
          • Stake snapshots
          • Pool distribution
  • Ledger
    • Eras
      • Byron
        • Blocks
        • Transactions
        • TX inputs
        • TX outputs
      • Shelley
        • Blocks
        • Transactions
        • TX inputs
        • TX outputs
      • Allegra
        • Blocks
        • Transactions
        • TX inputs
        • TX outputs
      • Mary
        • Blocks
        • Transactions
        • TX inputs
        • TX outputs
      • Alonzo
        • Blocks
        • Transactions
        • TX inputs
        • TX outputs
      • Babbage
        • Blocks
        • Transactions
        • TX inputs
        • TX outputs
      • Conway
        • Blocks
        • Transactions
        • TX inputs
        • TX outputs
    • Transaction attributes
      • Inputs
      • Outputs
      • Metadata
      • Fees
      • TTL
      • Certificates
      • Staking reward withdrawls
      • Protocol parameter updates
      • Auxiliary data hash
      • Validity interval start
      • Mint operations
      • Script data hash
      • Collateral inputs
      • Required signers
      • Collateral return
      • Total collateral
      • Reference inputs
  • Testing
    • Test framework for mocking Ouroboros conversations
    • CBOR deserialization and serialization
      • Protocol messages
      • Ledger
        • Block parsing
        • Transaction parsing
  • Misc
    • Address handling
      • Decode from bech32
      • Encode as bech32
      • Deserialize from CBOR
      • Retrieve staking key

Testing

gOuroboros includes automated tests that cover various aspects of its functionality, but not all. For more than the basics, manual testing is required.

Running the automated tests

make test

Manual testing

Various small test programs can be found in cmd/ in this repo or in the gOuroboros Starter Kit repo. Some of them can be run against public nodes via NtN protocols, but some may require access to the UNIX socket of a local node for NtC protocols.

Run chain-sync from the start of a particular era

This is useful for testing changes to the handling of ledger types for a particular era. It will decode each block and either print a summary line for the block or an error.

Start by building the test programs:

make

Run the chain-sync test program against a public mainnet node, starting at the beginning of the Shelley era:

./gouroboros -address backbone.cardano-mainnet.iohk.io:3001 -network mainnet -ntn chain-sync -bulk -start-era shelley

This will produce a LOT of output and take quite a few hours to reach chain tip. You're mostly looking for it to get through all blocks of the chosen start era before hitting the next era or chain tip

Dump details of a particular block

You can use the block-fetch program from gouroboros-starter-kit to fetch a particular block and dump its details. You must provide at least the block slot and hash. This is useful for debugging decoding problems, since it allows fetching a specific block and decoding it over and over.

BLOCK_FETCH_SLOT=120521627 BLOCK_FETCH_HASH=afd4c97e32003d9803a305011cbd8796e6b36bf61576567206887e35795b6e09 ./block-fetch

gouroboros's People

Contributors

agaffney avatar dependabot[bot] avatar igorcrevar avatar rakshasa avatar verbotenj avatar wolf31o2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

gouroboros's Issues

New()/Dial() functions hang when handshake fails

When the handshake fails, we're left sitting in setupConnection() waiting for the handshake to be complete. We need to figure out a way to get notified of the failure and bail out of the function

Implement handshake refusal

We currently can't properly cope when there are no matching versions in the handshake when acting as a server. This will require figuring out the various refusal reasons (we have consts for their IDs) and how they are formatted, and adding checks for those cases.

Require protocols to be explicitly started

We currently register the protocol handlers for all relevant protocols after the handshake completes. Instead, we should require the consumer to opt-in to each protocol.

The Ouroboros object should still call .New() on each protocol, but the call to the muxer's RegisterProtocol() function should be hidden behind a .Start() function. It probably also makes sense to move the protocol-specific callback function config to an arg to this .Start() function and out of the top level OuroborosOptions struct.

Implement TxSubmission2 mini-protocol

We only need support for TxSubmission2 (not TxSubmission), because we've chosen not to support pre-Alonzo protocol versions which would use TxSubmission.

Create Close() function for Ouroboros object

This should "gracefully" shut down the connection. This means setting an object flag and/or poking a channel to do things like stop reads, stop error collection, close the connection, etc.

Create unit test framework for mini-protocol message CBOR encoding/decoding

We need to be able to test that all of the mini-protocol message objects decode as expected from known CBOR and that an "identical" message object created from scratch properly encodes back into the same CBOR. We know that many of them will not for now, so we just want to create the framework and implement a few simple messages in each mini-protocol.

Support for specifying protocol diffusion mode

We currently only support the initiator-only diffusion mode, but we should at least make it explicit rather than implicit.

We should also add checks for messages that are marked as being from the initiator (not a response) when acting as a client in initiator-only mode. The cardano-node will produce an error like this when receiving a message marked as from the initiator while in this mode:

MuxError MuxInitiatorOnly "id = MiniProtocolNum 7"

Implement pipelining limits in various mini-protocols

The network spec doc says that each mini-protocol has its own built-in limit for the number of queued messages that it will handle between the muxer output and the mini-protocol input and that violating that limit is treated as a protocol violation which will result in a disconnect. We've definitely seen some weirdness with larger values of pipelined messages with chain-sync over NtN (but it resulted in a hang rather than a disconnect). Figure out the value for each mini-protocol and codify the limits on both the client and server side.

Finish implementing tx-submission

The messages and protocol state machine were implemented in #8, but there are no helper functions or test program.

We'll also need to figure out a way to do custom CBOR encoding of the params for certain messages based on this note in the network spec:

; The codec only accepts infinite−length list encoding for tsIdList!

race condition when stopping muxer

panic: close of closed channel

goroutine 1078 [running]:
github.com/cloudstruct/go-ouroboros-network/muxer.(*Muxer).Stop(0x4000076e80)
        /go/pkg/mod/github.com/cloudstruct/[email protected]/muxer/muxer.go:57 +0x94
github.com/cloudstruct/go-ouroboros-network.(*Ouroboros).Close(0x4000324460)
        /go/pkg/mod/github.com/cloudstruct/[email protected]/ouroboros.go:107 +0x30
github.com/cloudstruct/go-ouroboros-network.(*Ouroboros).setupConnection.func2(0x4000324460)
        /go/pkg/mod/github.com/cloudstruct/[email protected]/ouroboros.go:175 +0xb4
created by github.com/cloudstruct/go-ouroboros-network.(*Ouroboros).setupConnection
        /go/pkg/mod/github.com/cloudstruct/[email protected]/ouroboros.go:171 +0x254

Improve muxer/mini-protocol error handling

Any problem with decoding CBOR or sending/receiving messages in the wrong protocol state should cause the connection to be immediately terminated. We're currently just bubbling the errors up to the user and assuming they will do the right thing.

Instead, we should be breaking out of receive loops and closing connections within the library. We can still pass the error up to the user at the same time. Because everything is async, we'll need to figure out how to break out of all receive loops, or at least prevent the spewing of more errors from things trying to read from closed sockets.

This may be related to #24

Fix race condition around handshake and protocol registration

There's a race condition between the muxer and the registration of additional mini-protocols after the handshake completes. We need a way to "stop" the muxer from receiving new messages after the handshake until we have registered all of the mini-protocols.

Without this, it's possible for a client to send a message that we're not ready for and it throw an error because there's not an appropriate protocol handler registered yet.

Use stored CBOR of message when sending

When sending a message in Protocol.SendMessage(), we should check if the .Cbor() function returns any data and use that instead of doing the encoding ourselves.

Create integration test framework

This will require an actual cardano-node instance with an actual chain to sync. This could be the official testnet or a custom testnet that we generate blocks for.

CBOR parsing failure on local-tx-submission rejection message

This was seen in cloudstruct/go-cardano-submit-api when a transaction gets rejected.

{"level":"error","timestamp":"2022-05-05T19:06:24Z","caller":"api/api.go:154","msg":"failure communicating with node: protocol error: local-tx-submission: decode error: cbor: invalid map key type: []uint8","stacktrace":"github.com/cloudstruct/go-cardano-submit-api/internal/api.handleSubmitTx.func4\n\t/code/internal/api/api.go:154"}

Figure out issue with zero byte reads in muxer

I'll occasionally run into an error accessing index 0 in an array when the remote host closes the connection unexpectedly (usually in response to a "bad" message sent to them). There should be some additional error checking around this to detect the zero byte read (that we still try to decode as CBOR) to give a more useful error.

Add general unit tests

Create unit tests around all our CBOR utility functions and anything else that can be reasonably unit tested without external infra. Any testing around encoding/decoding of CBOR for mini-protocol messages will be handled in #63

Support pipelining of client requests

This will probably involve only checking for incoming messages when the protocol state machine is in a state with client agency. As a side note, the CBOR for all of the messages in the buffer is added to each parsed message, and we should figure out how to save only the CBOR for the current message.

Figure out a way to get friendly message names into error messages

With the move to centralized handling of protocol state and send/receive, we lost the name of protocol messages in error messages. Figure out a way to have the protocol.Message objects return a "name" string, or perhaps just have a map of numeric message type to a "name" string.

break out of Protocol recvLoop() on error

We currently pass along the error, but we don't exit the function, which causes the nil message object to be passed along to places that don't expect it, triggering the nil pointer reference and panic.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.