mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-23 03:41:34 +00:00
smartcontract: implement ContextItem
This commit is contained in:
parent
46db4e9d9d
commit
acea3867b2
2 changed files with 149 additions and 0 deletions
75
pkg/smartcontract/context/item.go
Normal file
75
pkg/smartcontract/context/item.go
Normal file
|
@ -0,0 +1,75 @@
|
|||
package context
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
// Item represents a transaction context item.
|
||||
type Item struct {
|
||||
Script util.Uint160
|
||||
Parameters []smartcontract.Parameter
|
||||
Signatures map[string][]byte
|
||||
}
|
||||
|
||||
type itemAux struct {
|
||||
Script util.Uint160 `json:"script"`
|
||||
Parameters []smartcontract.Parameter `json:"parameters"`
|
||||
Signatures map[string]string `json:"signatures"`
|
||||
}
|
||||
|
||||
// GetSignature returns signature for pub if present.
|
||||
func (it *Item) GetSignature(pub *keys.PublicKey) []byte {
|
||||
return it.Signatures[hex.EncodeToString(pub.Bytes())]
|
||||
}
|
||||
|
||||
// AddSignature adds a signature for pub.
|
||||
func (it *Item) AddSignature(pub *keys.PublicKey, sig []byte) {
|
||||
pubHex := hex.EncodeToString(pub.Bytes())
|
||||
it.Signatures[pubHex] = sig
|
||||
}
|
||||
|
||||
// MarshalJSON implements json.Marshaler interface.
|
||||
func (it Item) MarshalJSON() ([]byte, error) {
|
||||
ci := itemAux{
|
||||
Script: it.Script,
|
||||
Parameters: it.Parameters,
|
||||
Signatures: make(map[string]string, len(it.Signatures)),
|
||||
}
|
||||
|
||||
for key, sig := range it.Signatures {
|
||||
ci.Signatures[key] = hex.EncodeToString(sig)
|
||||
}
|
||||
|
||||
return json.Marshal(ci)
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler interface.
|
||||
func (it *Item) UnmarshalJSON(data []byte) error {
|
||||
ci := new(itemAux)
|
||||
if err := json.Unmarshal(data, ci); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sigs := make(map[string][]byte, len(ci.Signatures))
|
||||
for keyHex, sigHex := range ci.Signatures {
|
||||
_, err := keys.NewPublicKeyFromString(keyHex)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sig, err := hex.DecodeString(sigHex)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sigs[keyHex] = sig
|
||||
}
|
||||
|
||||
it.Signatures = sigs
|
||||
it.Script = ci.Script
|
||||
it.Parameters = ci.Parameters
|
||||
return nil
|
||||
}
|
74
pkg/smartcontract/context/item_test.go
Normal file
74
pkg/smartcontract/context/item_test.go
Normal file
|
@ -0,0 +1,74 @@
|
|||
package context
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestContextItem_AddSignature(t *testing.T) {
|
||||
item := &Item{Signatures: make(map[string][]byte)}
|
||||
|
||||
priv1, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
pub1 := priv1.PublicKey()
|
||||
sig1 := []byte{1, 2, 3}
|
||||
item.AddSignature(pub1, sig1)
|
||||
require.Equal(t, sig1, item.GetSignature(pub1))
|
||||
|
||||
priv2, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
pub2 := priv2.PublicKey()
|
||||
sig2 := []byte{5, 6, 7}
|
||||
item.AddSignature(pub2, sig2)
|
||||
require.Equal(t, sig2, item.GetSignature(pub2))
|
||||
require.Equal(t, sig1, item.GetSignature(pub1))
|
||||
}
|
||||
|
||||
func TestContextItem_MarshalJSON(t *testing.T) {
|
||||
priv1, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
priv2, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
expected := &Item{
|
||||
Script: util.Uint160{1, 2, 3},
|
||||
Parameters: []smartcontract.Parameter{{
|
||||
Type: smartcontract.SignatureType,
|
||||
Value: getRandomSlice(t, 64),
|
||||
}},
|
||||
Signatures: map[string][]byte{
|
||||
hex.EncodeToString(priv1.PublicKey().Bytes()): getRandomSlice(t, 64),
|
||||
hex.EncodeToString(priv2.PublicKey().Bytes()): getRandomSlice(t, 64),
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(expected)
|
||||
require.NoError(t, err)
|
||||
|
||||
actual := new(Item)
|
||||
require.NoError(t, json.Unmarshal(data, actual))
|
||||
assert.Equal(t, expected, actual)
|
||||
}
|
||||
|
||||
func getRandomSlice(t *testing.T, n int) []byte {
|
||||
src := rand.NewSource(time.Now().UnixNano())
|
||||
r := rand.New(src)
|
||||
data := make([]byte, n)
|
||||
_, err := io.ReadFull(r, data)
|
||||
require.NoError(t, err)
|
||||
return data
|
||||
}
|
Loading…
Reference in a new issue