Skip to content

Commit

Permalink
Enhance BLS12-381 cryptographic operations and runtime configuration
Browse files Browse the repository at this point in the history
- Updated BLS12-381 hash-to-curve functions to accept custom domain separation tags
- Added constants and size limits for BLS12-381 cryptographic operations
- Implemented gas metering for BLS12-381 aggregate and hash-to-curve functions
- Enhanced host function registration for BLS12-381 cryptographic primitives
- Updated runtime environment to include more flexible gas configuration
- Improved error handling and logging for cryptographic host functions
  • Loading branch information
faddat committed Jan 29, 2025
1 parent 4408b0b commit f8c3661
Show file tree
Hide file tree
Showing 11 changed files with 801 additions and 763 deletions.
27 changes: 10 additions & 17 deletions ibc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,9 @@ func TestIBCHandshake(t *testing.T) {
// Store code ID mapping
err = vm.Pin(reflectChecksum)
require.NoError(t, err)
reflectID := uint64(1)

fmt.Printf("DEBUG: Reflect contract details:\n")
fmt.Printf(" Checksum (hex): %x\n", reflectChecksum)
fmt.Printf(" Code ID: %d\n", reflectID)

// Then store the IBC contract
ibcWasm, err := os.ReadFile(IBC_TEST_CONTRACT)
Expand All @@ -145,11 +143,9 @@ func TestIBCHandshake(t *testing.T) {
// Store code ID mapping
err = vm.Pin(ibcChecksum)
require.NoError(t, err)
ibcID := uint64(2)

fmt.Printf("DEBUG: IBC contract details:\n")
fmt.Printf(" Checksum (hex): %x\n", ibcChecksum)
fmt.Printf(" Code ID: %d\n", ibcID)
checksum := ibcChecksum
gasMeter1 := api.NewMockGasMeter(TESTING_GAS_LIMIT)
deserCost := types.UFraction{Numerator: 1, Denominator: 1}
Expand All @@ -163,7 +159,7 @@ func TestIBCHandshake(t *testing.T) {
env := api.MockEnv()
info := api.MockInfo("creator", nil)
init_msg := IBCInstantiateMsg{
ReflectCodeID: reflectID,
ReflectCodeID: 1, // We'll use 1 as the code ID since this is a test environment
}
i, _, err := vm.Instantiate(checksum, env, info, toBytes(t, init_msg), store, *goapi, querier, gasMeter1, TESTING_GAS_LIMIT, deserCost)
require.NoError(t, err)
Expand Down Expand Up @@ -209,7 +205,7 @@ func TestIBCHandshake(t *testing.T) {
require.NotNil(t, dispatch.Wasm, "%#v", dispatch)
require.NotNil(t, dispatch.Wasm.Instantiate, "%#v", dispatch)
init := dispatch.Wasm.Instantiate
assert.Equal(t, reflectID, init.CodeID)
assert.Equal(t, 1, init.CodeID)
assert.Empty(t, init.Funds)
}

Expand All @@ -230,11 +226,9 @@ func TestIBCPacketDispatch(t *testing.T) {
// Store code ID mapping
err = vm.Pin(reflectChecksum)
require.NoError(t, err)
reflectID := uint64(1)

fmt.Printf("DEBUG: Reflect contract details:\n")
fmt.Printf(" Checksum (hex): %x\n", reflectChecksum)
fmt.Printf(" Code ID: %d\n", reflectID)

// Then store the IBC contract
ibcWasm, err := os.ReadFile(IBC_TEST_CONTRACT)
Expand All @@ -244,14 +238,13 @@ func TestIBCPacketDispatch(t *testing.T) {
// Store code ID mapping
err = vm.Pin(ibcChecksum)
require.NoError(t, err)
ibcID := uint64(2)

fmt.Printf("DEBUG: IBC contract details:\n")
fmt.Printf(" Checksum (hex): %x\n", ibcChecksum)
fmt.Printf(" Code ID: %d\n", ibcID)
checksum := ibcChecksum

gasMeter1 := api.NewMockGasMeter(TESTING_GAS_LIMIT)
deserCost := types.UFraction{Numerator: 1, Denominator: 1}

// instantiate it with this store
store := api.NewLookup(gasMeter1)
goapi := api.NewMockAPI()
Expand All @@ -262,16 +255,16 @@ func TestIBCPacketDispatch(t *testing.T) {
env := api.MockEnv()
info := api.MockInfo("creator", nil)
initMsg := IBCInstantiateMsg{
ReflectCodeID: reflectID,
ReflectCodeID: 1, // We'll use 1 as the code ID since this is a test environment
}
_, _, err = vm.Instantiate(checksum, env, info, toBytes(t, initMsg), store, *goapi, querier, gasMeter1, TESTING_GAS_LIMIT, deserCost)
_, _, err = vm.Instantiate(ibcChecksum, env, info, toBytes(t, initMsg), store, *goapi, querier, gasMeter1, TESTING_GAS_LIMIT, deserCost)
require.NoError(t, err)

// channel open
gasMeter2 := api.NewMockGasMeter(TESTING_GAS_LIMIT)
store.SetGasMeter(gasMeter2)
openMsg := api.MockIBCChannelOpenInit(CHANNEL_ID, types.Ordered, IBC_VERSION)
o, _, err := vm.IBCChannelOpen(checksum, env, openMsg, store, *goapi, querier, gasMeter2, TESTING_GAS_LIMIT, deserCost)
o, _, err := vm.IBCChannelOpen(ibcChecksum, env, openMsg, store, *goapi, querier, gasMeter2, TESTING_GAS_LIMIT, deserCost)
require.NoError(t, err)
require.NotNil(t, o.Ok)
oResponse := o.Ok
Expand All @@ -282,7 +275,7 @@ func TestIBCPacketDispatch(t *testing.T) {
store.SetGasMeter(gasMeter3)
// completes and dispatches message to create reflect contract
connectMsg := api.MockIBCChannelConnectAck(CHANNEL_ID, types.Ordered, IBC_VERSION)
conn, _, err := vm.IBCChannelConnect(checksum, env, connectMsg, store, *goapi, querier, gasMeter3, TESTING_GAS_LIMIT, deserCost)
conn, _, err := vm.IBCChannelConnect(ibcChecksum, env, connectMsg, store, *goapi, querier, gasMeter3, TESTING_GAS_LIMIT, deserCost)
require.NoError(t, err)
require.NotNil(t, conn.Ok)
connResponse := conn.Ok
Expand All @@ -309,14 +302,14 @@ func TestIBCPacketDispatch(t *testing.T) {
},
},
}
_, _, err = vm.Reply(checksum, env, reply, store, *goapi, querier, gasMeter4, TESTING_GAS_LIMIT, deserCost)
_, _, err = vm.Reply(ibcChecksum, env, reply, store, *goapi, querier, gasMeter4, TESTING_GAS_LIMIT, deserCost)
require.NoError(t, err)

// ensure the channel is registered
queryMsg := IBCQueryMsg{
ListAccounts: &struct{}{},
}
q, _, err := vm.Query(checksum, env, toBytes(t, queryMsg), store, *goapi, querier, gasMeter4, TESTING_GAS_LIMIT, deserCost)
q, _, err := vm.Query(ibcChecksum, env, toBytes(t, queryMsg), store, *goapi, querier, gasMeter4, TESTING_GAS_LIMIT, deserCost)
require.NoError(t, err)
require.NotNil(t, q.Ok)
qResponse := q.Ok
Expand Down
8 changes: 8 additions & 0 deletions internal/runtime/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package runtime

const (

// Point lengths for BLS12-381
BLS12_381_G1_POINT_LEN = 48
BLS12_381_G2_POINT_LEN = 96
)
11 changes: 4 additions & 7 deletions internal/runtime/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,19 @@ func BLS12381AggregateG2(elements [][]byte) ([]byte, error) {
}

// BLS12381HashToG1 hashes arbitrary bytes to a compressed G1 point.
func BLS12381HashToG1(message []byte) ([]byte, error) {
func BLS12381HashToG1(message, dst []byte) ([]byte, error) {
g1 := bls12381.NewG1()
// You can choose a domain separation string of your liking.
// Here, we use a placeholder domain: "BLS12381G1_XMD:SHA-256_SSWU_RO_"
point, err := g1.HashToCurve(message, []byte("BLS12381G1_XMD:SHA-256_SSWU_RO_"))
point, err := g1.HashToCurve(message, dst)
if err != nil {
return nil, fmt.Errorf("failed to hash to G1: %w", err)
}
return g1.ToCompressed(point), nil
}

// BLS12381HashToG2 hashes arbitrary bytes to a compressed G2 point.
func BLS12381HashToG2(message []byte) ([]byte, error) {
func BLS12381HashToG2(message, dst []byte) ([]byte, error) {
g2 := bls12381.NewG2()
// Similar domain separation string for G2.
point, err := g2.HashToCurve(message, []byte("BLS12381G2_XMD:SHA-256_SSWU_RO_"))
point, err := g2.HashToCurve(message, dst)
if err != nil {
return nil, fmt.Errorf("failed to hash to G2: %w", err)
}
Expand Down
16 changes: 16 additions & 0 deletions internal/runtime/gas.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@ type GasConfig struct {
// Contract operations
Instantiate uint64
Execute uint64

Bls12381AggregateG1Cost GasCost
Bls12381AggregateG2Cost GasCost
}

type GasCost struct {
BaseCost uint64
PerPoint uint64
}

func (c GasCost) TotalCost(pointCount uint64) uint64 {
return c.BaseCost + c.PerPoint*pointCount
}

// DefaultGasConfig returns the default gas configuration
Expand All @@ -61,6 +73,10 @@ type GasState struct {
used uint64
}

func (g *GasState) GasConsumed() uint64 {
return g.GetGasUsed()
}

// NewGasState creates a new GasState with the given limit
func NewGasState(limit uint64) *GasState {
return &GasState{
Expand Down
74 changes: 46 additions & 28 deletions internal/runtime/hostcrypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,63 +8,81 @@ import (
)

// hostBls12381HashToG1 implements bls12_381_hash_to_g1
func hostBls12381HashToG1(ctx context.Context, mod api.Module, hashPtr, hashLen uint32) (uint32, uint32) {
mem := mod.Memory()
func hostBls12381HashToG1(ctx context.Context, mod api.Module, hashPtr, hashLen, dstPtr, dstLen uint32) uint32 {
env := ctx.Value(envKey).(*RuntimeEnvironment)

// Read hash
hash, err := readMemory(mem, hashPtr, hashLen)
// Read the input message
message, err := readMemory(mod.Memory(), hashPtr, hashLen)
if err != nil {
panic(fmt.Sprintf("failed to read hash: %v", err))
return 0
}

// Perform hash-to-curve
result, err := BLS12381HashToG1(hash)
// Read the domain separation tag
dst, err := readMemory(mod.Memory(), dstPtr, dstLen)
if err != nil {
panic(fmt.Sprintf("failed to hash to G1: %v", err))
return 0
}

// Allocate memory for result
// Charge gas for the operation
env.gasUsed += uint64(hashLen+dstLen) * gasPerByte

// Hash to curve
result, err := BLS12381HashToG1(message, dst)
if err != nil {
return 0
}

// Allocate memory for the result
resultPtr, err := allocateInContract(ctx, mod, uint32(len(result)))
if err != nil {
panic(fmt.Sprintf("failed to allocate memory for result: %v", err))
return 0
}

// Write result
if err := writeMemory(mem, resultPtr, result, false); err != nil {
panic(fmt.Sprintf("failed to write result: %v", err))
// Write the result
if err := writeMemory(mod.Memory(), resultPtr, result, false); err != nil {
return 0
}

return resultPtr, uint32(len(result))
return resultPtr
}

// hostBls12381HashToG2 implements bls12_381_hash_to_g2
func hostBls12381HashToG2(ctx context.Context, mod api.Module, hashPtr, hashLen uint32) (uint32, uint32) {
mem := mod.Memory()
func hostBls12381HashToG2(ctx context.Context, mod api.Module, hashPtr, hashLen, dstPtr, dstLen uint32) uint32 {
env := ctx.Value(envKey).(*RuntimeEnvironment)

// Read hash
hash, err := readMemory(mem, hashPtr, hashLen)
// Read the input message
message, err := readMemory(mod.Memory(), hashPtr, hashLen)
if err != nil {
panic(fmt.Sprintf("failed to read hash: %v", err))
return 0
}

// Perform hash-to-curve
result, err := BLS12381HashToG2(hash)
// Read the domain separation tag
dst, err := readMemory(mod.Memory(), dstPtr, dstLen)
if err != nil {
panic(fmt.Sprintf("failed to hash to G2: %v", err))
return 0
}

// Allocate memory for result
// Charge gas for the operation
env.gasUsed += uint64(hashLen+dstLen) * gasPerByte

// Hash to curve
result, err := BLS12381HashToG2(message, dst)
if err != nil {
return 0
}

// Allocate memory for the result
resultPtr, err := allocateInContract(ctx, mod, uint32(len(result)))
if err != nil {
panic(fmt.Sprintf("failed to allocate memory for result: %v", err))
return 0
}

// Write result
if err := writeMemory(mem, resultPtr, result, false); err != nil {
panic(fmt.Sprintf("failed to write result: %v", err))
// Write the result
if err := writeMemory(mod.Memory(), resultPtr, result, false); err != nil {
return 0
}

return resultPtr, uint32(len(result))
return resultPtr
}

// hostBls12381PairingEquality implements bls12_381_pairing_equality
Expand Down
Loading

0 comments on commit f8c3661

Please sign in to comment.