smartcontract: implement ParameterContext
This commit is contained in:
parent
8819d4f970
commit
0d419d3899
2 changed files with 156 additions and 0 deletions
92
pkg/smartcontract/context/context.go
Normal file
92
pkg/smartcontract/context/context.go
Normal file
|
@ -0,0 +1,92 @@
|
|||
package context
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
// ParameterContext represents smartcontract parameter's context.
|
||||
type ParameterContext struct {
|
||||
// Type is a type of a verifiable item.
|
||||
Type string
|
||||
// Verifiable is an object which can be (de-)serialized.
|
||||
Verifiable io.Serializable
|
||||
// Items is a map from script hashes to context items.
|
||||
Items map[util.Uint160]*Item
|
||||
}
|
||||
|
||||
type paramContext struct {
|
||||
Type string `json:"type"`
|
||||
Hex string `json:"hex"`
|
||||
Items map[string]json.RawMessage `json:"items"`
|
||||
}
|
||||
|
||||
// MarshalJSON implements json.Marshaler interface.
|
||||
func (c ParameterContext) MarshalJSON() ([]byte, error) {
|
||||
bw := io.NewBufBinWriter()
|
||||
c.Verifiable.EncodeBinary(bw.BinWriter)
|
||||
if bw.Err != nil {
|
||||
return nil, bw.Err
|
||||
}
|
||||
items := make(map[string]json.RawMessage, len(c.Items))
|
||||
for u := range c.Items {
|
||||
data, err := json.Marshal(c.Items[u])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items["0x"+u.StringBE()] = data
|
||||
}
|
||||
pc := ¶mContext{
|
||||
Type: c.Type,
|
||||
Hex: hex.EncodeToString(bw.Bytes()),
|
||||
Items: items,
|
||||
}
|
||||
return json.Marshal(pc)
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler interface.
|
||||
func (c *ParameterContext) UnmarshalJSON(data []byte) error {
|
||||
pc := new(paramContext)
|
||||
if err := json.Unmarshal(data, pc); err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := hex.DecodeString(pc.Hex)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var verif io.Serializable
|
||||
switch pc.Type {
|
||||
case "Neo.Core.ContractTransaction":
|
||||
verif = new(transaction.Transaction)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type: %s", c.Type)
|
||||
}
|
||||
br := io.NewBinReaderFromBuf(data)
|
||||
verif.DecodeBinary(br)
|
||||
if br.Err != nil {
|
||||
return br.Err
|
||||
}
|
||||
items := make(map[util.Uint160]*Item, len(pc.Items))
|
||||
for h := range pc.Items {
|
||||
u, err := util.Uint160DecodeStringBE(strings.TrimPrefix(h, "0x"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
item := new(Item)
|
||||
if err := json.Unmarshal(pc.Items[h], item); err != nil {
|
||||
return err
|
||||
}
|
||||
items[u] = item
|
||||
}
|
||||
c.Type = pc.Type
|
||||
c.Verifiable = verif
|
||||
c.Items = items
|
||||
return nil
|
||||
}
|
64
pkg/smartcontract/context/context_test.go
Normal file
64
pkg/smartcontract/context/context_test.go
Normal file
|
@ -0,0 +1,64 @@
|
|||
package context
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestParameterContext_MarshalJSON(t *testing.T) {
|
||||
priv, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
tx := getContractTx()
|
||||
data := tx.GetSignedPart()
|
||||
sign := priv.Sign(data)
|
||||
|
||||
expected := &ParameterContext{
|
||||
Type: "Neo.Core.ContractTransaction",
|
||||
Verifiable: tx,
|
||||
Items: map[util.Uint160]*Item{
|
||||
priv.GetScriptHash(): {
|
||||
Script: priv.GetScriptHash(),
|
||||
Parameters: []smartcontract.Parameter{{
|
||||
Type: smartcontract.SignatureType,
|
||||
Value: sign,
|
||||
}},
|
||||
Signatures: map[string][]byte{
|
||||
hex.EncodeToString(priv.PublicKey().Bytes()): sign,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
data, err = json.Marshal(expected)
|
||||
require.NoError(t, err)
|
||||
|
||||
actual := new(ParameterContext)
|
||||
require.NoError(t, json.Unmarshal(data, actual))
|
||||
require.Equal(t, expected, actual)
|
||||
}
|
||||
|
||||
func getContractTx() *transaction.Transaction {
|
||||
tx := transaction.NewContractTX()
|
||||
tx.AddInput(&transaction.Input{
|
||||
PrevHash: util.Uint256{1, 2, 3, 4},
|
||||
PrevIndex: 5,
|
||||
})
|
||||
tx.AddOutput(&transaction.Output{
|
||||
AssetID: util.Uint256{7, 8, 9},
|
||||
Amount: 10,
|
||||
ScriptHash: util.Uint160{11, 12},
|
||||
})
|
||||
tx.Data = new(transaction.ContractTX)
|
||||
tx.Attributes = make([]transaction.Attribute, 0)
|
||||
tx.Scripts = make([]transaction.Witness, 0)
|
||||
tx.Hash()
|
||||
return tx
|
||||
}
|
Loading…
Reference in a new issue