Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 135 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,141 @@ Then install python requirements. Python >= 3.5 is required.

```pip install -r requirements.txt```

### Runtime Enhancements

ProtoSolGenerator includes enhanced runtime support for additional protobuf types and Google well-known types:

#### Float and Double Support

The runtime includes native support for protobuf `float` (32-bit) and `double` (64-bit) types:

- `_decode_float(uint256 p, bytes memory bs)` - Decodes protobuf float to bytes4
- `_encode_float(bytes4 x, uint256 p, bytes memory bs)` - Encodes bytes4 to protobuf float
- `_decode_double(uint256 p, bytes memory bs)` - Decodes protobuf double to bytes8
- `_encode_double(bytes8 x, uint256 p, bytes memory bs)` - Encodes bytes8 to protobuf double

These functions enable proper handling of floating-point validation constraints from buf/validate and other protobuf schemas.

#### Google Well-Known Types

Runtime libraries are provided for common Google protobuf types:

- **GoogleProtobufAny.sol** - Support for `google.protobuf.Any` messages
- **GoogleProtobufDuration.sol** - Support for `google.protobuf.Duration` messages
- **GoogleProtobufTimestamp.sol** - Support for `google.protobuf.Timestamp` messages
- **GoogleProtobufFieldDescriptorProto.sol** - Support for `google.protobuf.FieldDescriptorProto` messages

These libraries are automatically included when generating contracts that use the corresponding Google protobuf types.

### Solidity Compatibility

ProtoSolGenerator includes comprehensive compatibility features for Solidity development:

#### Reserved Keyword Handling

The generator automatically mangles protobuf field names that conflict with Solidity reserved keywords:

- **Automatic detection**: Comprehensive list of Solidity reserved keywords including types (uint256, bytes32, etc.), control flow (if, while, etc.), and language features (contract, library, etc.)
- **Safe mangling**: Conflicting field names are automatically suffixed with `_field` (e.g., `uint32` → `uint32_field`)
- **No manual intervention**: Field name conflicts are resolved transparently during code generation

#### Enhanced Parameter Processing

The plugin supports both value-based and boolean flag parameters:

```bash
# Boolean flags (automatically detected)
--sol_opt=gen_runtime
--sol_opt=use_builtin_enum

# Value-based parameters
--sol_opt=gen_runtime=MyRuntime.sol
--sol_opt=solc_version=0.8.19
```

This enables more flexible plugin configuration and better integration with build tools like buf.

### Circular Dependency Resolution

ProtoSolGenerator includes advanced handling for circular dependencies commonly found in validation schemas:

#### Automatic Detection

The generator automatically detects circular references in message structures, particularly in buf/validate types:

- **FieldRules** ↔ **MapRules**: Field rules can reference map validation rules
- **FieldRules** ↔ **RepeatedRules**: Field rules can reference repeated field validation rules
- **MapRules** → **FieldRules**: Map rules reference field rules for key/value validation

#### Bytes Field Solution

Circular dependencies are resolved by using `bytes` fields with encode/decode helpers:

```solidity
struct BufValidateFieldRules {
bytes map_field; // Circular reference: use encode/decode helpers
bytes repeated_field; // Circular reference: use encode/decode helpers
// ... other fields
}
```

The circular fields are marked with descriptive comments and can be serialized/deserialized using the standard protobuf encoding functions, maintaining full compatibility while avoiding Solidity compilation errors.

#### No Manual Intervention

Circular dependency resolution is automatic and transparent:
- Detected at generation time based on message and field type analysis
- Fields are automatically converted to `bytes` representation where needed
- Original protobuf semantics are preserved through encode/decode operations

### BSR Plugin Configuration

ProtoSolGenerator can be configured for distribution via the Buf Schema Registry (BSR):

#### Plugin Metadata

The included `buf.plugin.yaml` defines the plugin configuration:

```yaml
version: v1
name: buf.build/datachainlab/protoc-gen-solidity
plugin_version: v1.0.0
description: "Generate Solidity contracts from protobuf with validation support"
source_url: "https://github.com/datachainlab/solidity-protobuf"
deps:
- buf.build/protocolbuffers/protobuf
- buf.build/bufbuild/protovalidate
runtime:
python:
requirements:
- protobuf>=4.25.1
- wrapt
spdx_license_id: Apache-2.0
license_url: "https://github.com/datachainlab/solidity-protobuf/blob/master/LICENSE"
```

#### Local buf.gen.yaml Usage

For local development with the plugin:

```yaml
version: v2
plugins:
- local: ["python", "protobuf-solidity/src/protoc/plugin/gen_sol.py"]
out: contracts/generated
opt: gen_runtime=true
```

#### Plugin Options

The plugin supports various configuration options:

- `gen_runtime=true`: Generate runtime libraries (ProtoBufRuntime.sol, etc.)
- `gen_runtime=CustomRuntime.sol`: Generate with custom runtime filename
- `solc_version=0.8.19`: Target specific Solidity compiler version
- `for_linking`: Enable library linking mode for larger projects
- `pb_libname=Custom`: Set custom library name prefix

### Data Definition

Users can use the custom type definition to define their data structure. Below is an example:
Expand Down
15 changes: 15 additions & 0 deletions buf.plugin.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: v1
name: buf.build/cyberstorm/protoc-gen-solidity
plugin_version: v1.0.0-cyberstorm
description: "Generate Solidity contracts from protobuf with validation support and circular dependency fixes"
source_url: "https://github.com/cyberstorm-dev/solidity-protobuf"
deps:
- buf.build/protocolbuffers/protobuf
- buf.build/bufbuild/protovalidate
runtime:
python:
requirements:
- protobuf>=4.25.1
- wrapt
spdx_license_id: Apache-2.0
license_url: "https://github.com/datachainlab/solidity-protobuf/blob/master/LICENSE"
99 changes: 99 additions & 0 deletions protobuf-solidity/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# protobuf-solidity

A Protocol Buffers compiler plugin for generating Solidity code from `.proto` files.

## Features

### Message Generation
- Generates Solidity structs for Protocol Buffer messages
- Includes encoder/decoder functions for each message type
- Supports nested messages and repeated fields
- Handles all standard protobuf types (strings, integers, booleans, bytes)

### Contract Interface Generation
- Generates Solidity interfaces from Protocol Buffer service definitions
- Maps proto RPC methods to Solidity function signatures
- Maintains type safety between proto definitions and Solidity contracts
- Enables contract-first development with proto as single source of truth

## Usage

### Installation

Link the plugin for use with `protoc`:

```bash
ln -s src/protoc/plugin/gen_sol.py protoc-gen-solidity
chmod +x protoc-gen-solidity
```

### Basic Usage

Generate Solidity files from proto definitions:

```bash
protoc --solidity_out=./generated *.proto
```

### Proto Service to Contract Interface

Define a service in your `.proto` file:

```protobuf
service ContractInterface {
rpc RegisterIdentity(RegisterIdentityRequest) returns (RegisterIdentityResponse);
rpc GetIdentities(GetIdentitiesRequest) returns (GetIdentitiesResponse);
}
```

The plugin generates a corresponding Solidity interface:

```solidity
interface IContractInterface {
function registerIdentity(string memory domain, string memory identifier)
external returns (bool success, string memory error, string memory transaction_hash);
function getIdentities()
external returns (StandaloneAttestorStandaloneIdentity.Data[] memory identities);
}
```

### Contract Implementation

Implement the generated interface in your contract:

```solidity
contract MyContract is IContractInterface {
function registerIdentity(string memory domain, string memory identifier)
external override returns (bool success, string memory error, string memory transaction_hash) {
// Implementation
}
}
```

## Type Mapping

| Proto Type | Solidity Type |
|------------|---------------|
| `string` | `string memory` |
| `int32` | `int32` |
| `int64` | `int64` |
| `uint32` | `uint32` |
| `uint64` | `uint64` |
| `bool` | `bool` |
| `bytes` | `bytes memory` |
| `repeated T` | `T[] memory` |
| Message type | `LibraryName.Data memory` |

## Architecture

- **Message Types**: Generated as libraries with `Data` structs and encode/decode functions
- **Service Interfaces**: Generated as Solidity interfaces with function signatures matching RPC methods
- **Type Safety**: Compile-time verification that contracts match proto definitions
- **Modularity**: Each proto file generates corresponding Solidity libraries and interfaces

## Benefits

- **Single Source of Truth**: Proto files define both backend contracts and frontend types
- **Type Safety**: Compile-time checking ensures implementation matches specification
- **Consistency**: Same data structures across different parts of the application
- **Maintainability**: Changes to proto files automatically propagate to generated code
1 change: 1 addition & 0 deletions protobuf-solidity/protoc-gen-solidity
Loading