diff --git a/node/block_data.go b/node/block_data.go index c849ecc..be3d864 100644 --- a/node/block_data.go +++ b/node/block_data.go @@ -76,6 +76,9 @@ type BalanceUpdate struct { Delegate string `json:"delegate,omitempty"` Cycle uint64 `json:"cycle,omitempty"` Level uint64 `json:"level,omitempty"` + BondID struct { + TxRollup string `json:"tx_rollup"` + } `json:"bond_id,omitempty"` } // ImplicitOperationsResult - diff --git a/node/chain_data.go b/node/chain_data.go index 34ced58..d9b02ae 100644 --- a/node/chain_data.go +++ b/node/chain_data.go @@ -135,5 +135,8 @@ func (c *Content) UnmarshalJSON(data []byte) error { // IsManager - func IsManager(kind string) bool { - return kind == KindDelegation || kind == KindOrigination || kind == KindReveal || kind == KindTransaction || kind == KindSetDepositsLimit + return kind == KindOrigination || kind == KindReveal || kind == KindTransaction || kind == KindSetDepositsLimit || + kind == KindDelegation || kind == KindRegisterGlobalConstant || kind == KindTxRollupCommit || kind == KindTxRollupDispatchTickets || + kind == KindTxRollupFinalizeCommitment || kind == KindTxRollupOrigination || kind == KindTxRollupRejection || + kind == KindTxRollupRemoveCommitment || kind == KindTxRollupReturnBond || kind == KindTxRollupSubmitBatch } diff --git a/node/consts.go b/node/consts.go index 7f83ee4..e258816 100644 --- a/node/consts.go +++ b/node/consts.go @@ -31,6 +31,9 @@ const ( KindTxRollupRejection = "tx_rollup_rejection" KindTxRollupDispatchTickets = "tx_rollup_dispatch_tickets" KindTransferTicket = "transfer_ticket" + KindEvent = "event" + KindVdfRevelation = "vdf_revelation" + KindIncreasePaidStorage = "Increase_paid_storage" ) const ( diff --git a/node/operations.go b/node/operations.go index 429ee90..2da0c56 100644 --- a/node/operations.go +++ b/node/operations.go @@ -7,6 +7,17 @@ import ( "github.com/pkg/errors" ) +// OperationConstraint - +type OperationConstraint interface { + AccountActivation | Ballot | Delegation | DoubleBakingEvidence | + DoubleEndorsementEvidence | Endorsement | EndorsementWithSlot | + Origination | Proposal | Reveal | SeedNonceRevelation | Transaction | + RegisterGlobalConstant | DoublePreendorsementEvidence | SetDepositsLimit | + Preendorsement | Event | VdfRevelation | TxRollupCommit | TxRollupOrigination | + TxRollupDispatchTickets | TxRollupFinalizeCommitment | TxRollupRejection | + TxRollupRemoveCommitment | TxRollupSubmitBatch +} + // OperationGroup - type OperationGroup struct { Protocol string `json:"protocol"` @@ -30,330 +41,84 @@ func (op *Operation) UnmarshalJSON(data []byte) error { return err } + var err error switch op.Kind { case KindActivation: - var activation AccountActivation - if err := json.Unmarshal(data, &activation); err != nil { - return err - } - op.Body = activation + err = parseOperation[AccountActivation](data, op) case KindBallot: - var ballot Ballot - if err := json.Unmarshal(data, &ballot); err != nil { - return err - } - op.Body = ballot + err = parseOperation[Ballot](data, op) case KindDelegation: - var delegation Delegation - if err := json.Unmarshal(data, &delegation); err != nil { - return err - } - op.Body = delegation + err = parseOperation[Delegation](data, op) case KindDoubleBaking: - var evidence DoubleBakingEvidence - if err := json.Unmarshal(data, &evidence); err != nil { - return err - } - op.Body = evidence + err = parseOperation[DoubleBakingEvidence](data, op) case KindDoubleEndorsing: - var evidence DoubleEndorsementEvidence - if err := json.Unmarshal(data, &evidence); err != nil { - return err - } - op.Body = evidence + err = parseOperation[DoubleEndorsementEvidence](data, op) case KindEndorsement: - var endorsement Endorsement - if err := json.Unmarshal(data, &endorsement); err != nil { - return err - } - op.Body = endorsement + err = parseOperation[Endorsement](data, op) case KindEndorsementWithSlot: - var endorsement EndorsementWithSlot - if err := json.Unmarshal(data, &endorsement); err != nil { - return err - } - op.Body = endorsement + err = parseOperation[EndorsementWithSlot](data, op) case KindOrigination: - var origination Origination - if err := json.Unmarshal(data, &origination); err != nil { - return err - } - op.Body = origination + err = parseOperation[Origination](data, op) case KindProposal: - var proposal Proposal - if err := json.Unmarshal(data, &proposal); err != nil { - return err - } - op.Body = proposal + err = parseOperation[Proposal](data, op) case KindReveal: - var reveal Reveal - if err := json.Unmarshal(data, &reveal); err != nil { - return err - } - op.Body = reveal + err = parseOperation[Reveal](data, op) case KindNonceRevelation: - var seed SeedNonceRevelation - if err := json.Unmarshal(data, &seed); err != nil { - return err - } - op.Body = seed + err = parseOperation[SeedNonceRevelation](data, op) case KindTransaction: - var transaction Transaction - if err := json.Unmarshal(data, &transaction); err != nil { - return err - } - op.Body = transaction + err = parseOperation[Transaction](data, op) case KindRegisterGlobalConstant: - var register RegisterGlobalConstant - if err := json.Unmarshal(data, ®ister); err != nil { - return err - } - op.Body = register + err = parseOperation[RegisterGlobalConstant](data, op) case KindDoublePreendorsement: - var doublePreendorsement DoublePreendorsementEvidence - if err := json.Unmarshal(data, &doublePreendorsement); err != nil { - return err - } - op.Body = doublePreendorsement + err = parseOperation[DoublePreendorsementEvidence](data, op) case KindSetDepositsLimit: - var setDepositsLimit SetDepositsLimit - if err := json.Unmarshal(data, &setDepositsLimit); err != nil { - return err - } - op.Body = setDepositsLimit + err = parseOperation[SetDepositsLimit](data, op) case KindPreendorsement: - var preendorsement Preendorsement - if err := json.Unmarshal(data, &preendorsement); err != nil { - return err - } - op.Body = preendorsement + err = parseOperation[Preendorsement](data, op) + case KindEvent: + err = parseOperation[Event](data, op) + case KindVdfRevelation: + err = parseOperation[VdfRevelation](data, op) + case KindTxRollupOrigination: + err = parseOperation[TxRollupOrigination](data, op) + case KindTxRollupCommit: + err = parseOperation[TxRollupCommit](data, op) + case KindTxRollupDispatchTickets: + err = parseOperation[TxRollupDispatchTickets](data, op) + case KindTxRollupFinalizeCommitment: + err = parseOperation[TxRollupFinalizeCommitment](data, op) + case KindTxRollupRejection: + err = parseOperation[TxRollupRejection](data, op) + case KindTxRollupRemoveCommitment: + err = parseOperation[TxRollupRemoveCommitment](data, op) + case KindTxRollupSubmitBatch: + err = parseOperation[TxRollupSubmitBatch](data, op) + + } + return err +} + +func parseOperation[M OperationConstraint](data []byte, operation *Operation) error { + var model M + if err := json.Unmarshal(data, &model); err != nil { + return err } + operation.Body = model return nil } -// AccountActivation - -func (op Operation) AccountActivation() (AccountActivation, error) { - if op.Kind != KindActivation { - return AccountActivation{}, errors.Errorf("invalid kind of operation: %s", op.Kind) - } - if op.Body == nil { - return AccountActivation{}, errors.New("nil operation body") - } - activation, ok := op.Body.(AccountActivation) - if !ok { - return AccountActivation{}, errors.Errorf("invalid body type: %T", op.Body) - } - return activation, nil -} - -// Ballot - -func (op Operation) Ballot() (Ballot, error) { - if op.Kind != KindBallot { - return Ballot{}, errors.Errorf("invalid kind of operation: %s", op.Kind) - } - if op.Body == nil { - return Ballot{}, errors.New("nil operation body") - } - ballot, ok := op.Body.(Ballot) - if !ok { - return Ballot{}, errors.Errorf("invalid body type: %T", op.Body) - } - return ballot, nil -} - -// Endorsement - -func (op Operation) Endorsement() (Endorsement, error) { - if op.Kind != KindEndorsement { - return Endorsement{}, errors.Errorf("invalid kind of operation: %s", op.Kind) - } - if op.Body == nil { - return Endorsement{}, errors.New("nil operation body") - } - endorsement, ok := op.Body.(Endorsement) - if !ok { - return Endorsement{}, errors.Errorf("invalid body type: %T", op.Body) - } - return endorsement, nil -} - -// Preendorsement - -func (op Operation) Preendorsement() (Preendorsement, error) { - if op.Kind != KindPreendorsement { - return Preendorsement{}, errors.Errorf("invalid kind of operation: %s", op.Kind) - } - if op.Body == nil { - return Preendorsement{}, errors.New("nil operation body") - } - preendorsement, ok := op.Body.(Preendorsement) - if !ok { - return Preendorsement{}, errors.Errorf("invalid body type: %T", op.Body) - } - return preendorsement, nil -} - -// EndorsementWithSlot - -func (op Operation) EndorsementWithSlot() (EndorsementWithSlot, error) { - if op.Kind != KindEndorsementWithSlot { - return EndorsementWithSlot{}, errors.Errorf("invalid kind of operation: %s", op.Kind) - } - if op.Body == nil { - return EndorsementWithSlot{}, errors.New("nil operation body") - } - endorsement, ok := op.Body.(EndorsementWithSlot) - if !ok { - return EndorsementWithSlot{}, errors.Errorf("invalid body type: %T", op.Body) - } - return endorsement, nil -} - -// Delegation - -func (op Operation) Delegation() (Delegation, error) { - if op.Kind != KindDelegation { - return Delegation{}, errors.Errorf("invalid kind of operation: %s", op.Kind) - } - if op.Body == nil { - return Delegation{}, errors.New("nil operation body") - } - delegation, ok := op.Body.(Delegation) - if !ok { - return Delegation{}, errors.Errorf("invalid body type: %T", op.Body) - } - return delegation, nil -} - -// DoubleBakingEvidence - -func (op Operation) DoubleBakingEvidence() (DoubleBakingEvidence, error) { - if op.Kind != KindDelegation { - return DoubleBakingEvidence{}, errors.Errorf("invalid kind of operation: %s", op.Kind) - } - if op.Body == nil { - return DoubleBakingEvidence{}, errors.New("nil operation body") - } - evidence, ok := op.Body.(DoubleBakingEvidence) - if !ok { - return DoubleBakingEvidence{}, errors.Errorf("invalid body type: %T", op.Body) - } - return evidence, nil -} - -// DoubleEndorsementEvidence - -func (op Operation) DoubleEndorsementEvidence() (DoubleEndorsementEvidence, error) { - if op.Kind != KindDelegation { - return DoubleEndorsementEvidence{}, errors.Errorf("invalid kind of operation: %s", op.Kind) - } - if op.Body == nil { - return DoubleEndorsementEvidence{}, errors.New("nil operation body") - } - evidence, ok := op.Body.(DoubleEndorsementEvidence) - if !ok { - return DoubleEndorsementEvidence{}, errors.Errorf("invalid body type: %T", op.Body) - } - return evidence, nil -} - -// Origination - -func (op Operation) Origination() (Origination, error) { - if op.Kind != KindOrigination { - return Origination{}, errors.Errorf("invalid kind of operation: %s", op.Kind) - } - if op.Body == nil { - return Origination{}, errors.New("nil operation body") - } - origination, ok := op.Body.(Origination) - if !ok { - return Origination{}, errors.Errorf("invalid body type: %T", op.Body) - } - return origination, nil -} - -// Proposal - -func (op Operation) Proposal() (Proposal, error) { - if op.Kind != KindProposal { - return Proposal{}, errors.Errorf("invalid kind of operation: %s", op.Kind) - } - if op.Body == nil { - return Proposal{}, errors.New("nil operation body") - } - proposal, ok := op.Body.(Proposal) - if !ok { - return Proposal{}, errors.Errorf("invalid body type: %T", op.Body) - } - return proposal, nil -} - -// Reveal - -func (op Operation) Reveal() (Reveal, error) { - if op.Kind != KindReveal { - return Reveal{}, errors.Errorf("invalid kind of operation: %s", op.Kind) - } - if op.Body == nil { - return Reveal{}, errors.New("nil operation body") - } - reveal, ok := op.Body.(Reveal) - if !ok { - return Reveal{}, errors.Errorf("invalid body type: %T", op.Body) - } - return reveal, nil -} - -// Reveal - -func (op Operation) RegisterGlobalConstant() (RegisterGlobalConstant, error) { - if op.Kind != KindRegisterGlobalConstant { - return RegisterGlobalConstant{}, errors.Errorf("invalid kind of operation: %s", op.Kind) - } - if op.Body == nil { - return RegisterGlobalConstant{}, errors.New("nil operation body") - } - register, ok := op.Body.(RegisterGlobalConstant) - if !ok { - return RegisterGlobalConstant{}, errors.Errorf("invalid body type: %T", op.Body) - } - return register, nil -} - -// SeedNonceRevelation - -func (op Operation) SeedNonceRevelation() (SeedNonceRevelation, error) { - if op.Kind != KindNonceRevelation { - return SeedNonceRevelation{}, errors.Errorf("invalid kind of operation: %s", op.Kind) - } - if op.Body == nil { - return SeedNonceRevelation{}, errors.New("nil operation body") - } - seed, ok := op.Body.(SeedNonceRevelation) - if !ok { - return SeedNonceRevelation{}, errors.Errorf("invalid body type: %T", op.Body) - } - return seed, nil -} - -// SetDepositsLimit - -func (op Operation) SetDepositsLimit() (SetDepositsLimit, error) { - if op.Kind != KindSetDepositsLimit { - return SetDepositsLimit{}, errors.Errorf("invalid kind of operation: %s", op.Kind) - } - if op.Body == nil { - return SetDepositsLimit{}, errors.New("nil operation body") - } - tx, ok := op.Body.(SetDepositsLimit) - if !ok { - return SetDepositsLimit{}, errors.Errorf("invalid body type: %T", op.Body) - } - return tx, nil -} - -// Transaction - -func (op Operation) Transaction() (Transaction, error) { - if op.Kind != KindTransaction { - return Transaction{}, errors.Errorf("invalid kind of operation: %s", op.Kind) - } - if op.Body == nil { - return Transaction{}, errors.New("nil operation body") +// NewTypedOperation - +func NewTypedOperation[M OperationConstraint](operation Operation) (M, error) { + if operation.Body == nil { + var m M + return m, errors.New("nil operation body") } - tx, ok := op.Body.(Transaction) + model, ok := operation.Body.(M) if !ok { - return Transaction{}, errors.Errorf("invalid body type: %T", op.Body) + var m M + return m, errors.Errorf("invalid body type: %T", operation.Body) } - return tx, nil + return model, nil } // AccountActivation - @@ -490,6 +255,24 @@ type SetDepositsLimit struct { Metadata *ManagerOperationMetadata `json:"metadata"` } +// Event - +type Event struct { + Kind string `json:"kind"` + Source string `json:"source"` + Nonce int `json:"nonce"` + Type stdJSON.RawMessage `json:"type"` + Tag string `json:"tag"` + Payload stdJSON.RawMessage `json:"payload"` + Result OperationResult `json:"result"` +} + +// VdfRevelation - +type VdfRevelation struct { + Kind string `json:"kind"` + Solution []string `json:"solution"` + Metadata *ManagerOperationMetadata `json:"metadata,omitempty"` +} + // Transaction - type Transaction struct { Source string `json:"source"` @@ -511,9 +294,9 @@ type Parameters struct { // ManagerOperationMetadata - type ManagerOperationMetadata struct { - BalanceUpdates []BalanceUpdate `json:"balance_updates"` - OperationResult OperationResult `json:"operation_result"` - InternalOperationResults []InternalOperationResults `json:"internal_operation_results,omitempty"` + BalanceUpdates []BalanceUpdate `json:"balance_updates"` + OperationResult OperationResult `json:"operation_result"` + InternalOperationResults []Operation `json:"internal_operation_results,omitempty"` } // OnlyBalanceUpdatesMetadata - @@ -537,27 +320,15 @@ type OperationResult struct { BalanceUpdates []BalanceUpdate `json:"balance_updates,omitempty"` OriginatedContracts []string `json:"originated_contracts,omitempty"` ConsumedGas string `json:"consumed_gas,omitempty"` + ConsumedMilligas string `json:"consumed_milligas,omitempty"` StorageSize string `json:"storage_size,omitempty"` + OriginatedRollup string `json:"originated_rollup"` PaidStorageSizeDiff string `json:"paid_storage_size_diff,omitempty"` AllocatedDestinationContract bool `json:"allocated_destination_contract,omitempty"` + Level *uint64 `json:"level,omitempty"` Errors []ResultError `json:"errors,omitempty"` } -// InternalOperationResults - -type InternalOperationResults struct { - Kind string `json:"kind"` - Source string `json:"source"` - Nonce uint64 `json:"nonce"` - Amount string `json:"amount,omitempty"` - PublicKey string `json:"public_key,omitempty"` - Destination string `json:"destination,omitempty"` - Balance string `json:"balance,omitempty"` - Delegate string `json:"delegate,omitempty"` - Script *stdJSON.RawMessage `json:"script,omitempty"` - Parameters *Parameters `json:"paramaters,omitempty"` - Result OperationResult `json:"result"` -} - // ResultError - type ResultError struct { Kind string `json:"kind"` @@ -704,3 +475,153 @@ type EndorsementWithSlotEntity struct { type EndorsementOperation struct { Level uint64 `json:"level"` } + +// TxRollupOrigination - +type TxRollupOrigination struct { + Kind string `json:"kind"` + Source string `json:"source"` + Fee string `json:"fee"` + Counter string `json:"counter"` + GasLimit string `json:"gas_limit"` + StorageLimit string `json:"storage_limit"` + TxRollupOrigination any `json:"tx_rollup_origination"` + Metadata *ManagerOperationMetadata `json:"metadata,omitempty"` +} + +// TxRollupCommitment - +type TxRollupCommitment struct { + Level uint64 `json:"level"` + Messages []string `json:"messages"` + Predecessor string `json:"predecessor"` + InboxMerkleRoot string `json:"inbox_merkle_root"` +} + +// TxRollupCommit - +type TxRollupCommit struct { + Kind string `json:"kind"` + Source string `json:"source"` + Fee string `json:"fee"` + Counter string `json:"counter"` + GasLimit string `json:"gas_limit"` + StorageLimit string `json:"storage_limit"` + Rollup string `json:"rollup"` + Commitment TxRollupCommitment `json:"commitment"` + Metadata *ManagerOperationMetadata `json:"metadata,omitempty"` +} + +// TxRollupDispatchTickets - +type TxRollupDispatchTickets struct { + Kind string `json:"kind"` + Source string `json:"source"` + Fee string `json:"fee"` + Counter string `json:"counter"` + GasLimit string `json:"gas_limit"` + StorageLimit string `json:"storage_limit"` + TxRollup string `json:"tx_rollup"` + Level int `json:"level"` + ContextHash string `json:"context_hash"` + MessageIndex int `json:"message_index"` + MessageResultPath []string `json:"message_result_path"` + TicketsInfo []TicketsInfo `json:"tickets_info"` + Metadata *ManagerOperationMetadata `json:"metadata,omitempty"` +} + +// TicketsInfo - +type TicketsInfo struct { + Contents stdJSON.RawMessage `json:"contents"` + Ty stdJSON.RawMessage `json:"ty"` + Ticketer string `json:"ticketer"` + Amount string `json:"amount"` + Claimer string `json:"claimer"` +} + +// TxRollupFinalizeCommitment - +type TxRollupFinalizeCommitment struct { + Kind string `json:"kind"` + Source string `json:"source"` + Fee string `json:"fee"` + Counter string `json:"counter"` + GasLimit string `json:"gas_limit"` + StorageLimit string `json:"storage_limit"` + Rollup string `json:"rollup"` + Metadata *ManagerOperationMetadata `json:"metadata,omitempty"` +} + +// TxRollupRejection - +type TxRollupRejection struct { + Kind string `json:"kind"` + Source string `json:"source"` + Fee string `json:"fee"` + Counter string `json:"counter"` + GasLimit string `json:"gas_limit"` + StorageLimit string `json:"storage_limit"` + Rollup string `json:"rollup"` + Level int `json:"level"` + Message struct { + Batch string `json:"batch"` + } `json:"message"` + MessagePosition string `json:"message_position"` + MessagePath []string `json:"message_path"` + MessageResultHash string `json:"message_result_hash"` + MessageResultPath []string `json:"message_result_path"` + PreviousMessageResult struct { + ContextHash string `json:"context_hash"` + WithdrawListHash string `json:"withdraw_list_hash"` + } `json:"previous_message_result"` + PreviousMessageResultPath []string `json:"previous_message_result_path"` + Proof struct { + Version uint64 `json:"version"` + Before stdJSON.RawMessage `json:"before"` + After stdJSON.RawMessage `json:"after"` + State stdJSON.RawMessage `json:"proof"` + } `json:"proof"` + Metadata struct { + BalanceUpdates []struct { + Kind string `json:"kind"` + Contract string `json:"contract,omitempty"` + Change string `json:"change"` + Origin string `json:"origin"` + Category string `json:"category,omitempty"` + } `json:"balance_updates"` + OperationResult struct { + Status string `json:"status"` + BalanceUpdates []struct { + Kind string `json:"kind"` + Category string `json:"category,omitempty"` + Contract string `json:"contract,omitempty"` + BondID struct { + TxRollup string `json:"tx_rollup"` + } `json:"bond_id,omitempty"` + Change string `json:"change"` + Origin string `json:"origin"` + } `json:"balance_updates"` + ConsumedGas string `json:"consumed_gas"` + ConsumedMilligas string `json:"consumed_milligas"` + } `json:"operation_result"` + } `json:"metadata"` +} + +// TxRollupRemoveCommitment - +type TxRollupRemoveCommitment struct { + Kind string `json:"kind"` + Source string `json:"source"` + Fee string `json:"fee"` + Counter string `json:"counter"` + GasLimit string `json:"gas_limit"` + StorageLimit string `json:"storage_limit"` + Rollup string `json:"rollup"` + Metadata *ManagerOperationMetadata `json:"metadata,omitempty"` +} + +// TxRollupSubmitBatch - +type TxRollupSubmitBatch struct { + Kind string `json:"kind"` + Source string `json:"source"` + Fee string `json:"fee"` + Counter string `json:"counter"` + GasLimit string `json:"gas_limit"` + StorageLimit string `json:"storage_limit"` + Rollup string `json:"rollup"` + Content string `json:"content"` + Metadata *ManagerOperationMetadata `json:"metadata,omitempty"` +} diff --git a/tools/ast/address.go b/tools/ast/address.go index ab13d69..f7c705b 100644 --- a/tools/ast/address.go +++ b/tools/ast/address.go @@ -115,8 +115,7 @@ func (a *Address) Distinguish(x Distinguishable) (*MiguelNode, error) { // FromJSONSchema - func (a *Address) FromJSONSchema(data map[string]interface{}) error { - setOptimizedJSONSchema(&a.Default, data, forge.UnforgeContract) - return nil + return setOptimizedJSONSchema(&a.Default, data, forge.UnforgeContract, AddressValidator) } // FindByName - diff --git a/tools/ast/baker_hash.go b/tools/ast/baker_hash.go index bea7ff0..67cf1a8 100644 --- a/tools/ast/baker_hash.go +++ b/tools/ast/baker_hash.go @@ -82,8 +82,7 @@ func (s *BakerHash) Distinguish(x Distinguishable) (*MiguelNode, error) { // FromJSONSchema - func (s *BakerHash) FromJSONSchema(data map[string]interface{}) error { - setOptimizedJSONSchema(&s.Default, data, forge.UnforgeBakerHash) - return nil + return setOptimizedJSONSchema(&s.Default, data, forge.UnforgeBakerHash, BakerHashValidator) } // FindByName - diff --git a/tools/ast/bls.go b/tools/ast/bls.go index 7d2ac87..7910134 100644 --- a/tools/ast/bls.go +++ b/tools/ast/bls.go @@ -40,6 +40,11 @@ func (b *BLS12381fr) FindByName(name string, isEntrypoint bool) Node { return nil } +// FromJSONSchema - +func (b *BLS12381fr) FromJSONSchema(data map[string]interface{}) error { + return setBytesJSONSchema(&b.Default, data) +} + // // bls12_381_g1 // @@ -78,6 +83,11 @@ func (b *BLS12381g1) FindByName(name string, isEntrypoint bool) Node { return nil } +// FromJSONSchema - +func (b *BLS12381g1) FromJSONSchema(data map[string]interface{}) error { + return setBytesJSONSchema(&b.Default, data) +} + // // bls12_381_g2 // @@ -115,3 +125,8 @@ func (b *BLS12381g2) FindByName(name string, isEntrypoint bool) Node { } return nil } + +// FromJSONSchema - +func (b *BLS12381g2) FromJSONSchema(data map[string]interface{}) error { + return setBytesJSONSchema(&b.Default, data) +} diff --git a/tools/ast/chain_id.go b/tools/ast/chain_id.go index 94e1c31..f05e304 100644 --- a/tools/ast/chain_id.go +++ b/tools/ast/chain_id.go @@ -89,8 +89,7 @@ func (c *ChainID) Distinguish(x Distinguishable) (*MiguelNode, error) { // FromJSONSchema - func (c *ChainID) FromJSONSchema(data map[string]interface{}) error { - setOptimizedJSONSchema(&c.Default, data, forge.UnforgeChainID) - return nil + return setOptimizedJSONSchema(&c.Default, data, forge.UnforgeChainID, ChainIDValidator) } // FindByName - diff --git a/tools/ast/default.go b/tools/ast/default.go index 3d44642..8362593 100644 --- a/tools/ast/default.go +++ b/tools/ast/default.go @@ -194,12 +194,11 @@ func (d *Default) ToJSONSchema() (*JSONSchema, error) { // FromJSONSchema - func (d *Default) FromJSONSchema(data map[string]interface{}) error { - for key := range data { - if key == d.GetName() { - d.Value = data[key] - d.ValueKind = valueKindString - break - } + key := d.GetName() + + if value, ok := data[key]; ok { + d.Value = value + d.ValueKind = valueKindString } return nil } diff --git a/tools/ast/jsonschema.go b/tools/ast/jsonschema.go index ee1060a..a0d99e5 100644 --- a/tools/ast/jsonschema.go +++ b/tools/ast/jsonschema.go @@ -40,6 +40,9 @@ type JSONSchema struct { XOptions map[string]interface{} `json:"x-options,omitempty"` } +// Optimizer - +type Optimizer func(string) (string, error) + func getStringJSONSchema(d Default) *JSONSchema { return wrapObject(&JSONSchema{ Prim: d.Prim, @@ -70,49 +73,57 @@ func getAddressJSONSchema(d Default) *JSONSchema { } func setIntJSONSchema(d *Default, data map[string]interface{}) { - for key := range data { - if key == d.GetName() { - switch v := data[key].(type) { - case float64: - i := big.NewInt(0) - i, _ = big.NewFloat(v).Int(i) - d.Value = &types.BigInt{Int: i} - case string: - d.Value = types.NewBigIntFromString(v) - } - d.ValueKind = valueKindInt - break + key := d.GetName() + if value, ok := data[key]; ok { + switch v := value.(type) { + case float64: + i := big.NewInt(0) + i, _ = big.NewFloat(v).Int(i) + d.Value = &types.BigInt{Int: i} + case string: + d.Value = types.NewBigIntFromString(v) } + d.ValueKind = valueKindInt } } func setBytesJSONSchema(d *Default, data map[string]interface{}) error { - for key := range data { - if key == d.GetName() { - if _, err := hex.DecodeString(data[key].(string)); err != nil { - return errors.Errorf("invalid bytes string: %s=%v", key, data[key]) + key := d.GetName() + if value, ok := data[key]; ok { + if str, ok := value.(string); ok { + if err := BytesValidator(str); err != nil { + return err + } + if _, err := hex.DecodeString(str); err != nil { + return errors.Errorf("bytes decoding error: %s=%v", key, value) } - d.Value = data[key] + d.Value = value d.ValueKind = valueKindBytes - return nil } } return nil } -func setOptimizedJSONSchema(d *Default, data map[string]interface{}, optimizer func(string) (string, error)) { - for key, value := range data { - if key == d.GetName() { - val, err := optimizer(value.(string)) +func setOptimizedJSONSchema(d *Default, data map[string]interface{}, optimizer Optimizer, validator Validator[string]) error { + key := d.GetName() + if value, ok := data[key]; ok { + if str, ok := value.(string); ok { + if validator != nil { + if err := validator(str); err != nil { + return err + } + } + + val, err := optimizer(str) if err != nil { - val = value.(string) + val = str } d.ValueKind = valueKindString d.Value = val - break } } + return nil } type mergeFields struct { diff --git a/tools/ast/key.go b/tools/ast/key.go index 12708a2..dd97e38 100644 --- a/tools/ast/key.go +++ b/tools/ast/key.go @@ -83,8 +83,7 @@ func (k *Key) Distinguish(x Distinguishable) (*MiguelNode, error) { // FromJSONSchema - func (k *Key) FromJSONSchema(data map[string]interface{}) error { - setOptimizedJSONSchema(&k.Default, data, forge.UnforgePublicKey) - return nil + return setOptimizedJSONSchema(&k.Default, data, forge.UnforgePublicKey, PublicKeyValidator) } // FindByName - diff --git a/tools/ast/key_hash.go b/tools/ast/key_hash.go index 078fb19..45f5c17 100644 --- a/tools/ast/key_hash.go +++ b/tools/ast/key_hash.go @@ -83,8 +83,7 @@ func (k *KeyHash) Distinguish(x Distinguishable) (*MiguelNode, error) { // FromJSONSchema - func (k *KeyHash) FromJSONSchema(data map[string]interface{}) error { - setOptimizedJSONSchema(&k.Default, data, forge.UnforgeAddress) - return nil + return setOptimizedJSONSchema(&k.Default, data, forge.UnforgeAddress, nil) } // FindByName - diff --git a/tools/ast/list.go b/tools/ast/list.go index cdc4a29..3c67b24 100644 --- a/tools/ast/list.go +++ b/tools/ast/list.go @@ -133,7 +133,7 @@ func (list *List) ToJSONSchema() (*JSONSchema, error) { } switch list.Type.(type) { - case *Address, *Nat, *Mutez, *Int, *BakerHash, *BLS12381fr, *BLS12381g1, *BLS12381g2, *Bytes, *Key, *KeyHash, *ChainID, *Lambda, *Signature, *String, *List: + case *Address, *Nat, *Mutez, *Int, *BakerHash, *BLS12381fr, *BLS12381g1, *BLS12381g2, *Bytes, *Key, *KeyHash, *ChainID, *Lambda, *Signature, *String, *List, *Map: s.Items.Properties = child.Properties default: s.Items.Properties[list.Type.GetName()] = child diff --git a/tools/ast/script.go b/tools/ast/script.go index ac0e579..d560db7 100644 --- a/tools/ast/script.go +++ b/tools/ast/script.go @@ -36,7 +36,7 @@ func (s *Script) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &ast); err != nil { return err } - if len(ast) == 1 && ast[0].Prim == consts.PrimArray { + for len(ast) == 1 && ast[0].Prim == consts.PrimArray { ast = ast[0].Args } for i := range ast { diff --git a/tools/ast/set.go b/tools/ast/set.go index a79038c..2de4144 100644 --- a/tools/ast/set.go +++ b/tools/ast/set.go @@ -294,7 +294,9 @@ func (set *Set) GetJSONModel(model JSONModel) { } arr := make([]JSONModel, len(set.Data)) for i := range set.Data { - set.Data[i].GetJSONModel(arr[i]) + res := make(JSONModel) + set.Data[i].GetJSONModel(res) + arr = append(arr, res) } model[set.GetName()] = arr } diff --git a/tools/ast/signature.go b/tools/ast/signature.go index 466b7b5..18a2f40 100644 --- a/tools/ast/signature.go +++ b/tools/ast/signature.go @@ -82,8 +82,7 @@ func (s *Signature) Distinguish(x Distinguishable) (*MiguelNode, error) { // FromJSONSchema - func (s *Signature) FromJSONSchema(data map[string]interface{}) error { - setOptimizedJSONSchema(&s.Default, data, forge.UnforgeSignature) - return nil + return setOptimizedJSONSchema(&s.Default, data, forge.UnforgeSignature, SignatureValidator) } // FindByName - diff --git a/tools/ast/timestamp.go b/tools/ast/timestamp.go index e7d57f8..63e47b8 100644 --- a/tools/ast/timestamp.go +++ b/tools/ast/timestamp.go @@ -77,21 +77,20 @@ func (t *Timestamp) ToBaseNode(optimized bool) (*base.Node, error) { // FromJSONSchema - func (t *Timestamp) FromJSONSchema(data map[string]interface{}) error { - for key := range data { - if key == t.GetName() { - t.ValueKind = valueKindInt - switch val := data[key].(type) { - case string: - ts, err := time.Parse(time.RFC3339, val) - if err != nil { - return err - } - t.Value = types.NewBigInt(ts.UTC().Unix()) - case float64: - t.Value = types.NewBigInt(int64(val)) + key := t.GetName() + if value, ok := data[key]; ok { + t.ValueKind = valueKindInt + switch val := value.(type) { + case string: + ts, err := time.Parse(time.RFC3339, val) + if err != nil { + return errors.Wrapf(ErrValidation, "time should be in RFC3339 %s=%s", key, val) } - break + t.Value = types.NewBigInt(ts.UTC().Unix()) + case float64: + t.Value = types.NewBigInt(int64(val)) } + } return nil } diff --git a/tools/ast/tx_rollup_l2_address.go b/tools/ast/tx_rollup_l2_address.go new file mode 100644 index 0000000..d1519fb --- /dev/null +++ b/tools/ast/tx_rollup_l2_address.go @@ -0,0 +1,48 @@ +package ast + +import ( + "strings" + + "github.com/dipdup-net/go-lib/tools/consts" + "github.com/dipdup-net/go-lib/tools/forge" +) + +// TxRollupL2Address - +type TxRollupL2Address Address + +// NewTxRollupL2Address - +func NewTxRollupL2Address(depth int) *TxRollupL2Address { + return &TxRollupL2Address{ + Default: NewDefault(consts.TXROLLUPL2ADDRESS, 0, depth), + } +} + +// Compare - +func (a *TxRollupL2Address) Compare(second Comparable) (int, error) { + secondAddress, ok := second.(*TxRollupL2Address) + if !ok { + return 0, consts.ErrTypeIsNotComparable + } + if a.Value == secondAddress.Value { + return 0, nil + } + if a.ValueKind == secondAddress.ValueKind { + return strings.Compare(a.Value.(string), secondAddress.Value.(string)), nil + } + return compareNotOptimizedTypes(a.Default, secondAddress.Default, forge.Contract) +} + +// Distinguish - +func (a *TxRollupL2Address) Distinguish(x Distinguishable) (*MiguelNode, error) { + second, ok := x.(*TxRollupL2Address) + if !ok { + return nil, nil + } + if err := a.optimizeStringValue(forge.UnforgeContract); err != nil { + return nil, err + } + if err := second.optimizeStringValue(forge.UnforgeContract); err != nil { + return nil, err + } + return a.Default.Distinguish(&second.Default) +} diff --git a/tools/ast/untyped.go b/tools/ast/untyped.go index 9cc89c0..c35eb39 100644 --- a/tools/ast/untyped.go +++ b/tools/ast/untyped.go @@ -226,6 +226,8 @@ func typeNode(node *base.Node, depth int, id *int) (Node, error) { ast = NewChestKey(depth + 1) case consts.CONSTANT: ast = NewConstant(depth + 1) + case consts.TXROLLUPL2ADDRESS: + ast = NewTxRollupL2Address(depth + 1) default: return nil, errors.Wrap(consts.ErrUnknownPrim, node.Prim) } diff --git a/tools/ast/validators.go b/tools/ast/validators.go new file mode 100644 index 0000000..84800e9 --- /dev/null +++ b/tools/ast/validators.go @@ -0,0 +1,147 @@ +package ast + +import ( + "regexp" + "strings" + + "github.com/dipdup-net/go-lib/tools" + "github.com/dipdup-net/go-lib/tools/encoding" + "github.com/pkg/errors" +) + +// errors +var ( + ErrValidation = errors.New("validation error") +) + +// ValidatorConstraint - +type ValidatorConstraint interface { + ~string +} + +// Validator - +type Validator[T ValidatorConstraint] func(T) error + +var ( + hexRegex = regexp.MustCompile("^[0-9a-fA-F]+$") +) + +// AddressValidator - +func AddressValidator(value string) error { + switch len(value) { + case 44, 42: + if !hexRegex.MatchString(value) { + return errors.Wrapf(ErrValidation, "address '%s' should be hexademical without prefixes", value) + } + case 36: + if !tools.IsAddressLazy(value) { + return errors.Wrapf(ErrValidation, "invalid address '%s'", value) + } + if !tools.IsAddress(value) { + return errors.Wrapf(ErrValidation, "invalid address '%s'", value) + } + default: + return errors.Wrap(ErrValidation, "invalid address length") + } + + return nil +} + +// BakerHashValidator - +func BakerHashValidator(value string) error { + switch len(value) { + case 40: + if !hexRegex.MatchString(value) { + return errors.Wrapf(ErrValidation, "baker hash '%s' should be hexademical without prefixes", value) + } + case 36: + if !tools.IsBakerHash(value) { + return errors.Wrapf(ErrValidation, "invalid baker hash '%s'", value) + } + default: + return errors.Wrap(ErrValidation, "invalid baker hash length") + } + + return nil +} + +// PublicKeyValidator - +func PublicKeyValidator(value string) error { + switch len(value) { + case 68, 66: + if !hexRegex.MatchString(value) { + return errors.Wrapf(ErrValidation, "public key '%s' should be hexademical without prefixes", value) + } + case 55, 54: + if strings.HasPrefix(value, encoding.PrefixED25519PublicKey) || + strings.HasPrefix(value, encoding.PrefixP256PublicKey) || + strings.HasPrefix(value, encoding.PrefixSecp256k1PublicKey) { + return nil + } + return errors.Wrapf(ErrValidation, "invalid public key '%s'", value) + default: + return errors.Wrap(ErrValidation, "invalid public key length") + } + + return nil +} + +// BytesValidator - +func BytesValidator(value string) error { + if len(value)%2 > 0 { + return errors.Wrapf(ErrValidation, "invalid bytes in hex length '%s'", value) + } + if !hexRegex.MatchString(value) { + return errors.Wrapf(ErrValidation, "bytes '%s' should be hexademical without prefixes", value) + } + return nil +} + +// ChainIDValidator - +func ChainIDValidator(value string) error { + switch len(value) { + case 8: + if !hexRegex.MatchString(value) { + return errors.Wrapf(ErrValidation, "chain id '%s' should be hexademical without prefixes", value) + } + case 15: + if strings.HasPrefix(value, encoding.PrefixChainID) { + return nil + } + return errors.Wrapf(ErrValidation, "invalid chain id '%s'", value) + default: + return errors.Wrap(ErrValidation, "invalid chain id length") + } + + return nil +} + +// SignatureValidator - +func SignatureValidator(value string) error { + switch len(value) { + case 128: + if !hexRegex.MatchString(value) { + return errors.Wrapf(ErrValidation, "signature '%s' should be hexademical without prefixes", value) + } + case 96: + if strings.HasPrefix(value, encoding.PrefixGenericSignature) { + return nil + } + return errors.Wrapf(ErrValidation, "invalid signature '%s'", value) + case 98: + if strings.HasPrefix(value, encoding.PrefixP256Signature) { + return nil + } + return errors.Wrapf(ErrValidation, "invalid signature '%s'", value) + case 99: + if strings.HasPrefix(value, encoding.PrefixED25519Signature) || + strings.HasPrefix(value, encoding.PrefixSecp256k1Signature) { + return nil + } + return errors.Wrapf(ErrValidation, "invalid signature '%s'", value) + default: + return errors.Wrap(ErrValidation, "invalid signature length") + } + + return nil +} diff --git a/tools/ast/validators_test.go b/tools/ast/validators_test.go new file mode 100644 index 0000000..3bbecfc --- /dev/null +++ b/tools/ast/validators_test.go @@ -0,0 +1,203 @@ +package ast + +import ( + "testing" +) + +func TestAddressValidator(t *testing.T) { + tests := []struct { + name string + value string + wantErr bool + }{ + { + name: "test 1", + value: "016e4943f7a23ab9cbe56f48ff72f6c27e8956762400", + wantErr: false, + }, { + name: "test 2", + value: "KT1JdufSdfg3WyxWJcCRNsBFV9V3x9TQBkJ2", + wantErr: false, + }, { + name: "test 3", + value: "tz1KfEsrtDaA1sX7vdM4qmEPWuSytuqCDp5j", + wantErr: false, + }, { + name: "test 4", + value: "tz1KfEsrtDaA1sX7vdM4qmEPWuSytuqCDp5", + wantErr: true, + }, { + name: "test 5", + value: "0x6e4943f7a23ab9cbe56f48ff72f6c27e8956762400", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := AddressValidator(tt.value); (err != nil) != tt.wantErr { + t.Errorf("AddressValidator() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestBakerHashValidator(t *testing.T) { + tests := []struct { + name string + value string + wantErr bool + }{ + { + name: "test 1", + value: "94697e9229c88fac7d19d62e139ca6735f9569dd", + wantErr: false, + }, { + name: "test 2", + value: "SG1d1wsgMKvSstzZQ8L4WoskCesdWGzVt5k4", + wantErr: false, + }, { + name: "test 3", + value: "SG1d1wsgMKvSstzZQ8L4WoskCesdWGzVt5k", + wantErr: true, + }, { + name: "test 4", + value: "0x697e9229c88fac7d19d62e139ca6735f9569dd", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := BakerHashValidator(tt.value); (err != nil) != tt.wantErr { + t.Errorf("BakerHashValidator() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestPublicKeyValidator(t *testing.T) { + tests := []struct { + name string + value string + wantErr bool + }{ + { + name: "test 1", + value: "sppk7bMuoa8w2LSKz3XEuPsKx1WavsMLCWgbWG9CZNAsJg9eTmkXRPd", + wantErr: false, + }, { + name: "test 2", + value: "030ed412d33412ab4b71df0aaba07df7ddd2a44eb55c87bf81868ba09a358bc0e0", + wantErr: false, + }, { + name: "test 3", + value: "0x0ed412d33412ab4b71df0aaba07df7ddd2a44eb55c87bf81868ba09a358bc0e0", + wantErr: true, + }, { + name: "test 4", + value: "spsk7bMuoa8w2LSKz3XEuPsKx1WavsMLCWgbWG9CZNAsJg9eTmkXRPd", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := PublicKeyValidator(tt.value); (err != nil) != tt.wantErr { + t.Errorf("PublicKeyValidator() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestBytesValidator(t *testing.T) { + tests := []struct { + name string + value string + wantErr bool + }{ + { + name: "test 1", + value: "sppk7bMuoa8w2LSKz3XEuPsKx1WavsMLCWgbWG9CZNAsJg9eTmkXRPd", + wantErr: true, + }, { + name: "test 2", + value: "030ed412d33412ab4b71df0aaba07df7ddd2a44eb55c87bf81868ba09a358bc0e0", + wantErr: false, + }, { + name: "test 3", + value: "0x030ed412d33412ab4b71df0aaba07df7ddd2a44eb55c87bf81868ba09a358bc0e0", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := BytesValidator(tt.value); (err != nil) != tt.wantErr { + t.Errorf("BytesValidator() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestChainIDValidator(t *testing.T) { + tests := []struct { + name string + value string + wantErr bool + }{ + { + name: "test 1", + value: "7a06a770", + wantErr: false, + }, { + name: "test 2", + value: "NetXdQprcVkpaWU", + wantErr: false, + }, { + name: "test 3", + value: "0x06a770", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := ChainIDValidator(tt.value); (err != nil) != tt.wantErr { + t.Errorf("ChainIDValidator() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestSignatureValidator(t *testing.T) { + tests := []struct { + name string + value string + wantErr bool + }{ + { + name: "test 1", + value: "a04991b4e938cc42d6c01c42be3649a81a9f80d244d9b90e7ec4edf8e0a7b68b6c212da2fef076e48fed66802fa83442b960a36afdb3e60c3cf14d4010f41f03", + wantErr: false, + }, { + name: "test 2", + value: "sigixZejtj1GfDpyiWAQAmvbtnNmCXKyADqVvCaXJH9xHyhSnYYV8696Z3kkns5DNV7oMnMPfNzo3qm84DfEx1XG6saZmHiA", + wantErr: false, + }, { + name: "test 3", + value: "0x4991b4e938cc42d6c01c42be3649a81a9f80d244d9b90e7ec4edf8e0a7b68b6c212da2fef076e48fed66802fa83442b960a36afdb3e60c3cf14d4010f41f03", + wantErr: true, + }, { + name: "test 4", + value: "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7", + wantErr: false, + }, { + name: "test 5", + value: "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := SignatureValidator(tt.value); (err != nil) != tt.wantErr { + t.Errorf("SignatureValidator() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/tools/consts/primitives.go b/tools/consts/primitives.go index 9182a39..a052dd7 100644 --- a/tools/consts/primitives.go +++ b/tools/consts/primitives.go @@ -54,6 +54,7 @@ const ( OPENCHEST = "OPEN_CHEST" CHEST = "chest" CHESTKEY = "chest_key" + TXROLLUPL2ADDRESS = "tx_rollup_l2_address" ) // Data instructions diff --git a/tools/forge/transaction_test.go b/tools/forge/transaction_test.go index 3dc33b3..1e7d0e0 100644 --- a/tools/forge/transaction_test.go +++ b/tools/forge/transaction_test.go @@ -122,7 +122,7 @@ func TestTransaction(t *testing.T) { t.Errorf("UnmarshalFromString() error = %v", err) return } - transaction, err := operation.Transaction() + transaction, err := node.NewTypedOperation[node.Transaction](operation) if err != nil { t.Errorf("operation.Transaction() error = %v", err) return diff --git a/tools/literal.go b/tools/literal.go index 4a16d42..df31475 100644 --- a/tools/literal.go +++ b/tools/literal.go @@ -35,6 +35,7 @@ var ( addressRegex = regexp.MustCompile("(tz|KT)[0-9A-Za-z]{34}") operationHashRegex = regexp.MustCompile("(o)[0-9A-Za-z]{50}") bigMapKeyHashRegex = regexp.MustCompile("(expr)[0-9A-Za-z]{50}") + bakerHashRegex = regexp.MustCompile("(SG1)[0-9A-Za-z]{33}") ) // IsAddress - @@ -51,3 +52,8 @@ func IsOperationHash(str string) bool { func IsBigMapKeyHash(str string) bool { return bigMapKeyHashRegex.MatchString(str) } + +// IsBakerHash - +func IsBakerHash(str string) bool { + return bakerHashRegex.MatchString(str) +} diff --git a/tools/literal_test.go b/tools/literal_test.go index b9e7532..24a1e38 100644 --- a/tools/literal_test.go +++ b/tools/literal_test.go @@ -135,3 +135,28 @@ func TestIsAddress(t *testing.T) { }) } } + +func TestIsBakerHash(t *testing.T) { + tests := []struct { + name string + str string + want bool + }{ + { + name: "SG1d1wsgMKvSstzZQ8L4WoskCesdWGzVt5k4", + str: "SG1d1wsgMKvSstzZQ8L4WoskCesdWGzVt5k4", + want: true, + }, { + name: "SG1d1wsgMKvSstzZQ8L4WoskCesdWGzVt5k", + str: "SG1d1wsgMKvSstzZQ8L4WoskCesdWGzVt5k", + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IsBakerHash(tt.str); got != tt.want { + t.Errorf("IsBakerHash() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/tools/translator/converter.go b/tools/translator/converter.go index d6f53bf..4473c23 100644 --- a/tools/translator/converter.go +++ b/tools/translator/converter.go @@ -2,8 +2,7 @@ package translator import ( "io/ioutil" - "log" - "os" + "regexp" "github.com/yhirose/go-peg" ) @@ -13,7 +12,6 @@ type Converter struct { parser *peg.Parser grammar string err error - debug bool } // NewConverter - @@ -44,8 +42,6 @@ func NewConverter(opts ...ConverterOption) (Converter, error) { // FromFile - func (c Converter) FromFile(filename string) (string, error) { - c.trace() - michelson, err := readFileToString(filename) if err != nil { return "", err @@ -56,7 +52,7 @@ func (c Converter) FromFile(filename string) (string, error) { // FromString - func (c Converter) FromString(input string) (string, error) { - c.trace() + input = removeComments(input) ast, err := c.parser.ParseAndGetAst(input, nil) if err != nil { @@ -66,27 +62,18 @@ func (c Converter) FromString(input string) (string, error) { return NewJSONTranslator().Translate(ast) } -func (c Converter) trace() { - if c.debug { - c.parser.TracerEnter = func(name string, s string, v *peg.Values, d peg.Any, p int) { - log.Printf("Enter: %s %d %d", name, p, len(s)) - } - c.parser.TracerLeave = func(name string, s string, v *peg.Values, d peg.Any, p int, l int) { - if l != -1 { - log.Printf("Leave: %s %d %d", name, len(s), l+p) - } - } - } -} - func readFileToString(filename string) (string, error) { - f, err := os.Open(filename) - if err != nil { - return "", err - } - data, err := ioutil.ReadAll(f) + data, err := ioutil.ReadFile(filename) if err != nil { return "", err } return string(data), nil } + +var oneLineComment = regexp.MustCompile("#[^\n]*") +var multiLineComment = regexp.MustCompile(`\/\*[^\*]*\*/`) + +func removeComments(data string) string { + data = oneLineComment.ReplaceAllString(data, "") + return multiLineComment.ReplaceAllString(data, "") +} diff --git a/tools/translator/options.go b/tools/translator/options.go index 1077f6c..dcae5e9 100644 --- a/tools/translator/options.go +++ b/tools/translator/options.go @@ -21,10 +21,3 @@ func WithGrammar(grammar string) ConverterOption { c.grammar = grammar } } - -// WithDebug - -func WithDebug() ConverterOption { - return func(c *Converter) { - c.debug = true - } -} diff --git a/tools/translator/tests/long_lambda/code.json b/tools/translator/tests/long_lambda/code.json deleted file mode 100644 index 38bad17..0000000 --- a/tools/translator/tests/long_lambda/code.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - [ - { - "prim": "PUSH", - "args": [ - { - "prim": "string" - }, - { - "string": "WrongCondition: sp.view('tokens_infusable', storage.value.contract_registry, infusion.token_address, sp.TBool).open_some(message = 'Invalid view')" - } - ] - }, - { - "prim": "FAILWITH" - } - ] -] \ No newline at end of file diff --git a/tools/translator/tests/long_lambda/code.tz b/tools/translator/tests/long_lambda/code.tz deleted file mode 100644 index a788b1c..0000000 --- a/tools/translator/tests/long_lambda/code.tz +++ /dev/null @@ -1 +0,0 @@ -{ PUSH string "WrongCondition: sp.view(\"tokens_infusable\", storage.value.contract_registry, infusion.token_address, sp.TBool).open_some(message = 'Invalid view')"; FAILWITH } \ No newline at end of file diff --git a/tools/translator/translator.go b/tools/translator/translator.go index 923810c..7fa509a 100644 --- a/tools/translator/translator.go +++ b/tools/translator/translator.go @@ -165,14 +165,11 @@ func sanitizeString(token string) string { return token } +var primPattern = regexp.MustCompile("^parameter|storage|code|False|Elt|Left|None|Pair|Right|Some|True|Unit|PACK|UNPACK|BLAKE2B|SHA256|SHA512|ABS|ADD|AMOUNT|AND|BALANCE|CAR|CDR|CHECK_SIGNATURE|COMPARE|CONCAT|CONS|CREATE_CONTRACT|IMPLICIT_ACCOUNT|DIP|DROP|DUP|EDIV|EMPTY_MAP|EMPTY_SET|EQ|EXEC|FAILWITH|GE|GET|GT|HASH_KEY|IF|IF_CONS|IF_LEFT|IF_NONE|INT|LAMBDA|LE|LEFT|LOOP|LSL|LSR|LT|MAP|MEM|MUL|NEG|NEQ|NIL|NONE|NOT|NOW|OR|PAIR|PUSH|RIGHT|SIZE|SOME|SOURCE|SENDER|SELF|STEPS_TO_QUOTA|SUB|SWAP|TRANSFER_TOKENS|SET_DELEGATE|UNIT|UPDATE|XOR|ITER|LOOP_LEFT|ADDRESS|CONTRACT|ISNAT|CAST|RENAME|bool|contract|int|key|key_hash|lambda|list|map|big_map|nat|option|or|pair|set|signature|string|bytes|mutez|timestamp|unit|operation|address|SLICE|DIG|DUG|EMPTY_BIG_MAP|APPLY|chain_id|CHAIN_ID|LEVEL|SELF_ADDRESS|never|NEVER|UNPAIR|VOTING_POWER|TOTAL_VOTING_POWER|KECCAK|SHA3|PAIRING_CHECK|bls12_381_g1|bls12_381_g2|bls12_381_fr|sapling_state|sapling_transaction|SAPLING_EMPTY_STATE|SAPLING_VERIFY_UPDATE|ticket|TICKET|READ_TICKET|SPLIT_TICKET|JOIN_TICKETS|GET_AND_UPDATE|chest|chest_key|OPEN_CHEST|VIEW|view|constant|(UN)?P[PAI]*IR|D[IU]+P|C[A]+R$") + func validatePrimitive(prim string) error { - valid, err := regexp.MatchString( - "^parameter|storage|code|False|Elt|Left|None|Pair|Right|Some|True|Unit|PACK|UNPACK|BLAKE2B|SHA256|SHA512|ABS|ADD|AMOUNT|AND|BALANCE|CAR|CDR|CHECK_SIGNATURE|COMPARE|CONCAT|CONS|CREATE_CONTRACT|IMPLICIT_ACCOUNT|DIP|DROP|DUP|EDIV|EMPTY_MAP|EMPTY_SET|EQ|EXEC|FAILWITH|GE|GET|GT|HASH_KEY|IF|IF_CONS|IF_LEFT|IF_NONE|INT|LAMBDA|LE|LEFT|LOOP|LSL|LSR|LT|MAP|MEM|MUL|NEG|NEQ|NIL|NONE|NOT|NOW|OR|PAIR|PUSH|RIGHT|SIZE|SOME|SOURCE|SENDER|SELF|STEPS_TO_QUOTA|SUB|SWAP|TRANSFER_TOKENS|SET_DELEGATE|UNIT|UPDATE|XOR|ITER|LOOP_LEFT|ADDRESS|CONTRACT|ISNAT|CAST|RENAME|bool|contract|int|key|key_hash|lambda|list|map|big_map|nat|option|or|pair|set|signature|string|bytes|mutez|timestamp|unit|operation|address|SLICE|DIG|DUG|EMPTY_BIG_MAP|APPLY|chain_id|CHAIN_ID|LEVEL|SELF_ADDRESS|never|NEVER|UNPAIR|VOTING_POWER|TOTAL_VOTING_POWER|KECCAK|SHA3|PAIRING_CHECK|bls12_381_g1|bls12_381_g2|bls12_381_fr|sapling_state|sapling_transaction|SAPLING_EMPTY_STATE|SAPLING_VERIFY_UPDATE|ticket|TICKET|READ_TICKET|SPLIT_TICKET|JOIN_TICKETS|GET_AND_UPDATE|chest|chest_key|OPEN_CHEST|VIEW|view|constant$", - prim) - if err != nil { - return err - } - if !valid { + // TODO: handle macros + add FAIL prim + if !primPattern.MatchString(prim) { return errors.Errorf("Invalid primitive %s", prim) } return nil