diff --git a/go.sum b/go.sum index d555d81..83d6607 100644 --- a/go.sum +++ b/go.sum @@ -24,6 +24,9 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/maestro-org/go-sdk v1.1.3 h1:ORkeu1NXesRkdW7Pr5N956GojCibmGMdjXuO5jNAOZk= +github.com/maestro-org/go-sdk v1.1.3/go.mod h1:EYaRwFT8nkwFzZsN6xK256j+r7ASUUn9p44RlaqYjE8= +github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/plutusencoder/plutus.go b/plutusencoder/plutus.go index 4b0fbec..78043ec 100644 --- a/plutusencoder/plutus.go +++ b/plutusencoder/plutus.go @@ -235,13 +235,13 @@ func MarshalPlutus(v interface{}) (*PlutusData.PlutusData, error) { types := reflect.TypeOf(v) values := reflect.ValueOf(v) //get Container type - fields, ok := types.FieldByName("_") - typeOfStruct := fields.Tag.Get("plutusType") - if typeOfStruct == "Map" { - isMap = true - } + ok := types.Kind() == reflect.Struct if ok { + fields, _ := types.FieldByName("_") typeOfStruct := fields.Tag.Get("plutusType") + if typeOfStruct == "Map" { + isMap = true + } Constr := fields.Tag.Get("plutusConstr") if Constr != "" { parsedConstr, err := strconv.Atoi(Constr) @@ -266,6 +266,7 @@ func MarshalPlutus(v interface{}) (*PlutusData.PlutusData, error) { overallContainer = PlutusData.PlutusDefArray{} isIndef = false default: + fmt.Println(typeOfStruct) return nil, fmt.Errorf("error: unknown type") } //get fields @@ -293,6 +294,35 @@ func MarshalPlutus(v interface{}) (*PlutusData.PlutusData, error) { } } switch typeOfField { + case "Bool": + if values.Field(i).Kind() != reflect.Bool { + return nil, fmt.Errorf("error: Bool field is not bool") + } + var boolPD PlutusData.PlutusData + switch values.Field(i).Bool() { + case true: + boolPD = PlutusData.PlutusData{ + TagNr: 122, + PlutusDataType: PlutusData.PlutusArray, + Value: PlutusData.PlutusDefArray{}, + } + case false: + boolPD = PlutusData.PlutusData{ + TagNr: 121, + PlutusDataType: PlutusData.PlutusArray, + Value: PlutusData.PlutusDefArray{}, + } + } + if isMap { + nameBytes := serialization.NewCustomBytes(name) + overallContainer.(map[serialization.CustomBytes]PlutusData.PlutusData)[nameBytes] = boolPD + } else { + if isIndef { + overallContainer = append(overallContainer.(PlutusData.PlutusIndefArray), boolPD) + } else { + overallContainer = append(overallContainer.(PlutusData.PlutusDefArray), boolPD) + } + } case "Bytes": if values.Field(i).Kind() != reflect.Slice { return nil, fmt.Errorf("error: Bytes field is not a slice") @@ -507,7 +537,28 @@ func MarshalPlutus(v interface{}) (*PlutusData.PlutusData, error) { } if !ok { - return nil, fmt.Errorf("error: no _ field") + switch types.Kind() { + case reflect.String: + return &PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusBytes, + Value: []byte(values.Interface().(string)), + TagNr: containerConstr, + }, nil + case reflect.Int: + return &PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusInt, + Value: values.Interface().(int), + TagNr: containerConstr, + }, nil + case reflect.Slice: + return &PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusBytes, + Value: values.Interface().([]byte), + TagNr: containerConstr, + }, nil + default: + return nil, fmt.Errorf("error: unknown type") + } } ptype := PlutusData.PlutusArray if isMap { @@ -541,6 +592,7 @@ func CborUnmarshal(data string, v interface{}, network byte) error { func UnmarshalPlutus(data *PlutusData.PlutusData, v interface{}, network byte) (ret error) { defer func() { if r := recover(); r != nil { + fmt.Println("Recovered in UnmarshalPlutus", r) ret = errors.New("error unmarshalling") } }() @@ -606,11 +658,9 @@ func unmarshalPlutus(data *PlutusData.PlutusData, v interface{}, Plutusconstr ui tps := types.Elem() //values := reflect.ValueOf(tps) //isStruct := tps.Kind() == reflect.Struct - fields, ok := tps.FieldByName("_") + ok := tps.Kind() == reflect.Struct if ok { - if !ok { - return fmt.Errorf("error: no _ field") - } + fields, _ := tps.FieldByName("_") switch data.PlutusDataType { case PlutusData.PlutusArray: if reflect.TypeOf(v).Kind() != reflect.Ptr { @@ -637,6 +687,13 @@ func unmarshalPlutus(data *PlutusData.PlutusData, v interface{}, Plutusconstr ui reflect.ValueOf(v).Elem().Field(idx + 1).Set(reflect.ValueOf(addr)) continue } + if tps.Field(idx+1).Type.String() == "bool" { + if tps.Field(idx+1).Type.String() != "bool" { + return fmt.Errorf("error: Bool field is not bool") + } + reflect.ValueOf(v).Elem().Field(idx + 1).SetBool(pAEl.TagNr == 122) + continue + } switch pAEl.PlutusDataType { case PlutusData.PlutusBytes: if tps.Field(idx+1).Type.String() != "[]uint8" { @@ -718,6 +775,13 @@ func unmarshalPlutus(data *PlutusData.PlutusData, v interface{}, Plutusconstr ui reflect.ValueOf(v).Elem().Field(idx + 1).Set(reflect.ValueOf(addr)) continue } + if tps.Field(idx+1).Type.String() == "bool" { + if tps.Field(idx+1).Type.String() != "bool" { + return fmt.Errorf("error: Bool field is not bool") + } + reflect.ValueOf(v).Elem().Field(idx + 1).SetBool(pAEl.TagNr == 122) + continue + } switch pAEl.PlutusDataType { case PlutusData.PlutusBytes: if tps.Field(idx+1).Type.String() != "[]uint8" { @@ -808,6 +872,9 @@ func unmarshalPlutus(data *PlutusData.PlutusData, v interface{}, Plutusconstr ui addr := DecodePlutusAddress(pAEl, network) reflect.ValueOf(v).Elem().FieldByName(idx).Set(reflect.ValueOf(addr)) continue + case "bool": + reflect.ValueOf(v).Elem().FieldByName(idx).SetBool(pAEl.TagNr == 122) + continue case "[]uint8": if pAEl.PlutusDataType != PlutusData.PlutusBytes { return fmt.Errorf("error: Bytes field is not a slice") @@ -881,7 +948,46 @@ func unmarshalPlutus(data *PlutusData.PlutusData, v interface{}, Plutusconstr ui return fmt.Errorf("error: unknown type") } } else { - return fmt.Errorf("error: no _ field") + if types.Kind() == reflect.Ptr { + types = types.Elem() + } + switch types.Kind() { + case reflect.String: + if data.PlutusDataType != PlutusData.PlutusBytes { + return fmt.Errorf("error: Bytes field is not a slice") + } + if reflect.TypeOf(v).Kind() != reflect.Ptr { + return fmt.Errorf("error: v is not a pointer") + } + if reflect.TypeOf(v).Elem().Kind() != reflect.String { + return fmt.Errorf("error: v is not a string") + } + reflect.ValueOf(v).Elem().SetString(string(data.Value.([]byte))) + case reflect.Int: + if data.PlutusDataType != PlutusData.PlutusInt { + return fmt.Errorf("error: Int field is not int64") + } + if reflect.TypeOf(v).Kind() != reflect.Ptr { + return fmt.Errorf("error: v is not a pointer") + } + if reflect.TypeOf(v).Elem().Kind() != reflect.Int { + return fmt.Errorf("error: v is not an int") + } + reflect.ValueOf(v).Elem().SetInt(int64(data.Value.(uint64))) + case reflect.Slice: + if data.PlutusDataType != PlutusData.PlutusBytes { + return fmt.Errorf("error: Bytes field is not a slice") + } + if reflect.TypeOf(v).Kind() != reflect.Ptr { + return fmt.Errorf("error: v is not a pointer") + } + if reflect.TypeOf(v).Elem().Kind() != reflect.Slice { + return fmt.Errorf("error: v is not a slice") + } + reflect.ValueOf(v).Elem().Set(reflect.ValueOf(data.Value)) + default: + return fmt.Errorf("error: unknown type") + } } return nil diff --git a/serialization/MultiAsset/MultiAsset.go b/serialization/MultiAsset/MultiAsset.go index c2f8918..c0e8fd1 100644 --- a/serialization/MultiAsset/MultiAsset.go +++ b/serialization/MultiAsset/MultiAsset.go @@ -212,5 +212,4 @@ func (ma MultiAsset[V]) Filter(f func(policy Policy.PolicyId, asset AssetName.As } } return result - } diff --git a/serialization/Redeemer/Redeemer.go b/serialization/Redeemer/Redeemer.go index f279283..3a3d67d 100644 --- a/serialization/Redeemer/Redeemer.go +++ b/serialization/Redeemer/Redeemer.go @@ -16,7 +16,7 @@ var RdeemerTagNames = map[RedeemerTag]string{ 0: "spend", 1: "mint", 2: "certificate", - 3: "withdrawal", + 3: "withdraw", } type ExecutionUnits struct { @@ -25,7 +25,9 @@ type ExecutionUnits struct { Steps int64 } -/** +/* +* + Clone creates a deep copy of the ExecutionUnits. Returns: @@ -38,7 +40,9 @@ func (ex *ExecutionUnits) Clone() ExecutionUnits { } } -/** +/* +* + Sum adds the memory and step of another ExecutionUnits to the current instance. @@ -59,7 +63,9 @@ type Redeemer struct { ExUnits ExecutionUnits } -/** +/* +* + Clone creates a deep copy of the Redeemer. Returns: diff --git a/serialization/Transaction/Transaction_test.go b/serialization/Transaction/Transaction_test.go index 54ccb4a..7e88b71 100644 --- a/serialization/Transaction/Transaction_test.go +++ b/serialization/Transaction/Transaction_test.go @@ -59,6 +59,6 @@ func TestId(t *testing.T) { } txId := tx.Id() if hex.EncodeToString(txId.Payload) != "49289fa2198208f49f62303aab86d06fb1ff960c812ee98d88c7a5cebb29b615" { - t.Error("Invalid transaction ID", hex.EncodeToString(txId.Payload), "Expected", "f60200a1049ffff4f6") + t.Error("Invalid transaction ID", hex.EncodeToString(txId.Payload), "Expected", "49289fa2198208f49f62303aab86d06fb1ff960c812ee98d88c7a5cebb29b615") } } diff --git a/serialization/TransactionBody/TransactionBody.go b/serialization/TransactionBody/TransactionBody.go index 0ce57b3..4c60cf6 100644 --- a/serialization/TransactionBody/TransactionBody.go +++ b/serialization/TransactionBody/TransactionBody.go @@ -32,6 +32,26 @@ type TransactionBody struct { ReferenceInputs []TransactionInput.TransactionInput `cbor:"18,keyasint,omitempty"` } +type CborBody struct { + Inputs []TransactionInput.TransactionInput `cbor:"0,keyasint"` + Outputs []TransactionOutput.TransactionOutput `cbor:"1,keyasint"` + Fee int64 `cbor:"2,keyasint"` + Ttl int64 `cbor:"3,keyasint,omitempty"` + Certificates *Certificate.Certificates `cbor:"4,keyasint,omitempty"` + Withdrawals *Withdrawal.Withdrawal `cbor:"5,keyasint,omitempty"` + UpdateProposals []any `cbor:"6,keyasint,omitempty"` + AuxiliaryDataHash []byte `cbor:"7,keyasint,omitempty"` + ValidityStart int64 `cbor:"8,keyasint,omitempty"` + Mint MultiAsset.MultiAsset[int64] `cbor:"9,keyasint,omitempty"` + ScriptDataHash []byte `cbor:"11,keyasint,omitempty"` + Collateral []TransactionInput.TransactionInput `cbor:"13,keyasint,omitempty"` + RequiredSigners []serialization.PubKeyHash `cbor:"14,keyasint,omitempty"` + NetworkId []byte `cbor:"15,keyasint,omitempty"` + CollateralReturn *TransactionOutput.TransactionOutput `cbor:"16,keyasint,omitempty"` + TotalCollateral int `cbor:"17,keyasint,omitempty"` + ReferenceInputs []TransactionInput.TransactionInput `cbor:"18,keyasint,omitempty"` +} + func (tx *TransactionBody) Hash() ([]byte, error) { bytes, err := cbor.Marshal(tx) if err != nil { @@ -56,3 +76,27 @@ func (tx *TransactionBody) Id() (serialization.TransactionId, error) { } return serialization.TransactionId{bytes}, nil } + +func (tx *TransactionBody) MarshalCBOR() ([]byte, error) { + cborBody := CborBody{ + Inputs: tx.Inputs, + Outputs: tx.Outputs, + Fee: tx.Fee, + Ttl: tx.Ttl, + Certificates: tx.Certificates, + Withdrawals: tx.Withdrawals, + UpdateProposals: tx.UpdateProposals, + AuxiliaryDataHash: tx.AuxiliaryDataHash, + ValidityStart: tx.ValidityStart, + Mint: tx.Mint, + ScriptDataHash: tx.ScriptDataHash, + Collateral: tx.Collateral, + RequiredSigners: tx.RequiredSigners, + NetworkId: tx.NetworkId, + CollateralReturn: tx.CollateralReturn, + TotalCollateral: tx.TotalCollateral, + ReferenceInputs: tx.ReferenceInputs, + } + em, _ := cbor.CanonicalEncOptions().EncMode() + return em.Marshal(cborBody) +} diff --git a/txBuilding/Backend/Base/Base.go b/txBuilding/Backend/Base/Base.go index ccd648c..3bef355 100644 --- a/txBuilding/Backend/Base/Base.go +++ b/txBuilding/Backend/Base/Base.go @@ -92,7 +92,7 @@ type Output struct { } func (o Output) ToUTxO(txHash string) *UTxO.UTxO { - txOut, _ := o.ToTransactionOutput() + txOut := o.ToTransactionOutput() decodedTxHash, _ := hex.DecodeString(txHash) utxo := UTxO.UTxO{ Input: TransactionInput.TransactionInput{ @@ -104,7 +104,7 @@ func (o Output) ToUTxO(txHash string) *UTxO.UTxO { return &utxo } -func (o Output) ToTransactionOutput() (TransactionOutput.TransactionOutput, PlutusData.PlutusData) { +func (o Output) ToTransactionOutput() TransactionOutput.TransactionOutput { address, _ := Address.DecodeAddress(o.Address) amount := o.Amount lovelace_amount := 0 @@ -145,13 +145,25 @@ func (o Output) ToTransactionOutput() (TransactionOutput.TransactionOutput, Plut cbor.Unmarshal(decoded, &x) datum = x + tx_out := TransactionOutput.TransactionOutput{ + PostAlonzo: TransactionOutput.TransactionOutputAlonzo{ + Address: address, + Amount: final_amount.ToAlonzoValue(), + Datum: &PlutusData.DatumOption{ + Inline: &datum, + DatumType: 1, + }, + }, + IsPostAlonzo: true, + } + return tx_out } tx_out := TransactionOutput.TransactionOutput{PreAlonzo: TransactionOutput.TransactionOutputShelley{ Address: address, Amount: final_amount, DatumHash: datum_hash, HasDatum: len(datum_hash.Payload) > 0}, IsPostAlonzo: false} - return tx_out, datum + return tx_out } type TxUtxos struct {