Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure persisted zeto state and nullifiers are all 32 bytes #506

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
3 changes: 0 additions & 3 deletions domains/integration-test/helpers/zeto_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ import (
"github.com/stretchr/testify/assert"
)

//go:embed abis/ZetoFactory.json
var ZetoFactoryJSON []byte

type ZetoHelper struct {
t *testing.T
rpc rpcbackend.Backend
Expand Down
7 changes: 5 additions & 2 deletions domains/zeto/integration-test/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ import (
"github.com/hyperledger/firefly-signer/pkg/abi"
"github.com/hyperledger/firefly-signer/pkg/rpcbackend"
"github.com/kaleido-io/paladin/core/pkg/testbed"
"github.com/kaleido-io/paladin/domains/integration-test/helpers"
"github.com/kaleido-io/paladin/toolkit/pkg/log"
"github.com/kaleido-io/paladin/toolkit/pkg/pldapi"
"github.com/kaleido-io/paladin/toolkit/pkg/solutils"
"github.com/kaleido-io/paladin/toolkit/pkg/tktypes"
)

//go:embed abis/ZetoFactory.json
var zetoFactoryJSON []byte

type ZetoDomainContracts struct {
FactoryAddress *tktypes.EthAddress
factoryAbi abi.ABI
Expand All @@ -51,7 +53,7 @@ type cloneableContract struct {
}

func newZetoDomainContracts() *ZetoDomainContracts {
factory := solutils.MustLoadBuild(helpers.ZetoFactoryJSON)
factory := solutils.MustLoadBuild(zetoFactoryJSON)

return &ZetoDomainContracts{
factoryAbi: factory.ABI,
Expand Down Expand Up @@ -235,5 +237,6 @@ func registerImpl(ctx context.Context, name string, domainContracts *ZetoDomainC
},
ABI: abi.ABI{abiFunc},
})
log.L(ctx).Infof("Registered implementation %s", name)
return err
}
11 changes: 7 additions & 4 deletions domains/zeto/integration-test/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ func (s *zetoDomainTestSuite) testZetoFungible(t *testing.T, tokenName string, u
assert.Regexp(t, "PD012216: Transaction reverted OwnableUnauthorizedAccount.*", err)

if useBatch {
// for testing the batch circuits, we transfer 50 which would require 3 UTXOs (>2)
amount1 := 10
// for testing the batch circuits, we transfer 55 which would require 3 UTXOs (>2)
amount1 := 15
amount2 := 40
log.L(ctx).Info("*************************************")
log.L(ctx).Infof("Transfer %d from controller to recipient1 (%d) and recipient2 (%d)", amount1+amount2, amount1, amount2)
Expand All @@ -209,6 +209,9 @@ func (s *zetoDomainTestSuite) testZetoFungible(t *testing.T, tokenName string, u
// one for the recipient (value=25)
expectedCoins := 2
if useBatch {
// one for the controller from the successful transaction as change (value=5)
// one for the recipient1 (value=15)
// one for the recipient2 (value=40)
expectedCoins = 3
}
if len(coins) != expectedCoins {
Expand All @@ -219,9 +222,9 @@ func (s *zetoDomainTestSuite) testZetoFungible(t *testing.T, tokenName string, u
require.Len(t, coins, expectedCoins)

if useBatch {
assert.Equal(t, int64(10), coins[0].Data.Amount.Int().Int64()) // state for recipient1
assert.Equal(t, int64(15), coins[0].Data.Amount.Int().Int64()) // state for recipient1
assert.Equal(t, int64(40), coins[1].Data.Amount.Int().Int64()) // state for recipient2
assert.Equal(t, int64(10), coins[2].Data.Amount.Int().Int64()) // change for controller
assert.Equal(t, int64(5), coins[2].Data.Amount.Int().Int64()) // change for controller
assert.Equal(t, controllerAddr.String(), coins[2].Data.Owner.String())
} else {
assert.Equal(t, int64(25), coins[0].Data.Amount.Int().Int64()) // state for recipient1
Expand Down
2 changes: 1 addition & 1 deletion domains/zeto/internal/zeto/handler_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func parseStatesFromEvent(txID tktypes.HexBytes, states []tktypes.HexUint256) []
refs := make([]*prototk.StateUpdate, len(states))
for i, state := range states {
refs[i] = &prototk.StateUpdate{
Id: state.String(),
Id: hexUint256To32ByteHexString(&state),
TransactionId: txID.String(),
}
}
Expand Down
8 changes: 8 additions & 0 deletions domains/zeto/internal/zeto/handler_events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,11 @@ func TestHandleWithdrawEvent(t *testing.T) {
err = z.handleWithdrawEvent(ctx, merkleTree, storage, ev, "Zeto_AnonNullifier", res)
assert.ErrorContains(t, err, "PD210061: Failed to update merkle tree for the UTXOWithdraw event. PD210056: Failed to create new node index from hash. 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
}

func TestParseStatesFromEvent(t *testing.T) {
txID := tktypes.MustParseHexBytes("0x1234")
states := parseStatesFromEvent(txID, []tktypes.HexUint256{*tktypes.MustParseHexUint256("0x1234"), *tktypes.MustParseHexUint256("0x0")})
assert.Len(t, states, 2)
assert.Equal(t, "0000000000000000000000000000000000000000000000000000000000001234", states[0].Id)
assert.Equal(t, "0000000000000000000000000000000000000000000000000000000000000000", states[1].Id)
}
2 changes: 1 addition & 1 deletion domains/zeto/internal/zeto/states.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func (z *Zeto) makeNewState(ctx context.Context, useNullifiers bool, coin *types
if err != nil {
return nil, err
}
hashStr := hash.String()
hashStr := hexUint256To32ByteHexString(hash)
newState := &pb.NewState{
Id: &hashStr,
SchemaId: z.coinSchema.Id,
Expand Down
12 changes: 10 additions & 2 deletions domains/zeto/internal/zeto/zeto.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package zeto
import (
"context"
_ "embed"
"encoding/hex"
"encoding/json"
"math/big"

Expand Down Expand Up @@ -459,6 +460,11 @@ func intTo32ByteSlice(bigInt *big.Int) (res []byte) {
return bigInt.FillBytes(make([]byte, 32))
}

func hexUint256To32ByteHexString(v *tktypes.HexUint256) string {
paddedBytes := intTo32ByteSlice(v.Int())
return hex.EncodeToString(paddedBytes)
}

func (z *Zeto) Sign(ctx context.Context, req *prototk.SignRequest) (*prototk.SignResponse, error) {
switch req.PayloadType {
case zetosignerapi.PAYLOAD_DOMAIN_ZETO_NULLIFIER:
Expand Down Expand Up @@ -505,12 +511,14 @@ func (z *Zeto) ValidateStateHashes(ctx context.Context, req *prototk.ValidateSta
log.L(ctx).Errorf("Error hashing state data: %s", err)
return nil, i18n.NewError(ctx, msgs.MsgErrorHashOutputState, err)
}
hashString := hexUint256To32ByteHexString(hash)
if state.Id == "" {
// if the requested state ID is empty, we simply set it
res.StateIds = append(res.StateIds, hash.String())
res.StateIds = append(res.StateIds, hashString)
} else {
// if the requested state ID is set, we compare it with the calculated hash
if hash.String() != state.Id {
stateId := tktypes.MustParseHexUint256(state.Id)
if hash.Int().Cmp(stateId.Int()) != 0 {
log.L(ctx).Errorf("State hash mismatch (hashed vs. received): %s != %s", hash.String(), state.Id)
return nil, i18n.NewError(ctx, msgs.MsgErrorStateHashMismatch, hash.String(), state.Id)
}
Expand Down
Loading