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

feat: add perun types && fix: add marshal method for script group #225

Open
wants to merge 10 commits into
base: v2
Choose a base branch
from
24 changes: 24 additions & 0 deletions transaction/script_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package transaction

import (
"encoding/json"

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/nervosnetwork/ckb-sdk-go/v2/types"
)
Expand Down Expand Up @@ -43,3 +44,26 @@ func (r *ScriptGroup) UnmarshalJSON(input []byte) error {
}
return nil
}

func (r *ScriptGroup) MarshalJSON() ([]byte, error) {
toHexutilArray := func(in []uint32) []hexutil.Uint {
out := make([]hexutil.Uint, len(in))
for i, data := range in {
out[i] = hexutil.Uint(data)
}
return out
}

jsonObj := struct {
Script *types.Script `json:"script"`
GroupType types.ScriptType `json:"group_type"`
InputIndices []hexutil.Uint `json:"input_indices"`
OutputIndices []hexutil.Uint `json:"output_indices"`
}{
Script: r.Script,
GroupType: r.GroupType,
InputIndices: toHexutilArray(r.InputIndices),
OutputIndices: toHexutilArray(r.OutputIndices),
}
return json.Marshal(jsonObj)
}
7 changes: 4 additions & 3 deletions transaction/signer_test/signer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import (
"encoding/json"
"errors"
"fmt"
"os"
"runtime/debug"
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/nervosnetwork/ckb-sdk-go/v2/crypto/secp256k1"
Expand All @@ -13,9 +17,6 @@ import (
"github.com/nervosnetwork/ckb-sdk-go/v2/transaction/signer/omnilock"
"github.com/nervosnetwork/ckb-sdk-go/v2/types"
"github.com/stretchr/testify/assert"
"os"
"runtime/debug"
"testing"
)

func TestIsSingleSigMatched(t *testing.T) {
Expand Down
196 changes: 196 additions & 0 deletions types/molecule/offchain_type.go
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this file generated?

Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
package molecule

import (
"bytes"
"errors"
"strconv"
"strings"
)

type OffChainParticipantBuilder struct {
pub_key SEC1EncodedPubKey
payment_script Script
unlock_script Script
}

func (s *OffChainParticipantBuilder) Build() OffChainParticipant {
b := new(bytes.Buffer)

totalSize := HeaderSizeUint * (3 + 1)
offsets := make([]uint32, 0, 3)

offsets = append(offsets, totalSize)
totalSize += uint32(len(s.pub_key.AsSlice()))
offsets = append(offsets, totalSize)
totalSize += uint32(len(s.payment_script.AsSlice()))
offsets = append(offsets, totalSize)
totalSize += uint32(len(s.unlock_script.AsSlice()))

b.Write(packNumber(Number(totalSize)))

for i := 0; i < len(offsets); i++ {
b.Write(packNumber(Number(offsets[i])))
}

b.Write(s.pub_key.AsSlice())
b.Write(s.payment_script.AsSlice())
b.Write(s.unlock_script.AsSlice())
return OffChainParticipant{inner: b.Bytes()}
}

func (s *OffChainParticipantBuilder) PubKey(v SEC1EncodedPubKey) *OffChainParticipantBuilder {
s.pub_key = v
return s
}

func (s *OffChainParticipantBuilder) PaymentScript(v Script) *OffChainParticipantBuilder {
s.payment_script = v
return s
}

func (s *OffChainParticipantBuilder) UnlockScript(v Script) *OffChainParticipantBuilder {
s.unlock_script = v
return s
}

func NewOffChainParticipantBuilder() *OffChainParticipantBuilder {
return &OffChainParticipantBuilder{pub_key: SEC1EncodedPubKeyDefault(), payment_script: ScriptDefault(), unlock_script: ScriptDefault()}
}

type OffChainParticipant struct {
inner []byte
}

func OffChainParticipantFromSliceUnchecked(slice []byte) *OffChainParticipant {
return &OffChainParticipant{inner: slice}
}
func (s *OffChainParticipant) AsSlice() []byte {
return s.inner
}

func OffChainParticipantDefault() OffChainParticipant {
return *OffChainParticipantFromSliceUnchecked([]byte{155, 0, 0, 0, 16, 0, 0, 0, 49, 0, 0, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
}

func OffChainParticipantFromSlice(slice []byte, compatible bool) (*OffChainParticipant, error) {
sliceLen := len(slice)
if uint32(sliceLen) < HeaderSizeUint {
errMsg := strings.Join([]string{"HeaderIsBroken", "OffChainParticipant", strconv.Itoa(int(sliceLen)), "<", strconv.Itoa(int(HeaderSizeUint))}, " ")
return nil, errors.New(errMsg)
}

totalSize := unpackNumber(slice)
if Number(sliceLen) != totalSize {
errMsg := strings.Join([]string{"TotalSizeNotMatch", "OffChainParticipant", strconv.Itoa(int(sliceLen)), "!=", strconv.Itoa(int(totalSize))}, " ")
return nil, errors.New(errMsg)
}

if uint32(sliceLen) < HeaderSizeUint*2 {
errMsg := strings.Join([]string{"TotalSizeNotMatch", "OffChainParticipant", strconv.Itoa(int(sliceLen)), "<", strconv.Itoa(int(HeaderSizeUint * 2))}, " ")
return nil, errors.New(errMsg)
}

offsetFirst := unpackNumber(slice[HeaderSizeUint:])
if uint32(offsetFirst)%HeaderSizeUint != 0 || uint32(offsetFirst) < HeaderSizeUint*2 {
errMsg := strings.Join([]string{"OffsetsNotMatch", "OffChainParticipant", strconv.Itoa(int(offsetFirst % 4)), "!= 0", strconv.Itoa(int(offsetFirst)), "<", strconv.Itoa(int(HeaderSizeUint * 2))}, " ")
return nil, errors.New(errMsg)
}

if sliceLen < int(offsetFirst) {
errMsg := strings.Join([]string{"HeaderIsBroken", "OffChainParticipant", strconv.Itoa(int(sliceLen)), "<", strconv.Itoa(int(offsetFirst))}, " ")
return nil, errors.New(errMsg)
}

fieldCount := uint32(offsetFirst)/HeaderSizeUint - 1
if fieldCount < 3 {
return nil, errors.New("FieldCountNotMatch")
} else if !compatible && fieldCount > 3 {
return nil, errors.New("FieldCountNotMatch")
}

offsets := make([]uint32, fieldCount)

for i := 0; i < int(fieldCount); i++ {
offsets[i] = uint32(unpackNumber(slice[HeaderSizeUint:][int(HeaderSizeUint)*i:]))
}
offsets = append(offsets, uint32(totalSize))

for i := 0; i < len(offsets); i++ {
if i&1 != 0 && offsets[i-1] > offsets[i] {
return nil, errors.New("OffsetsNotMatch")
}
}

var err error

_, err = SEC1EncodedPubKeyFromSlice(slice[offsets[0]:offsets[1]], compatible)
if err != nil {
return nil, err
}

_, err = ScriptFromSlice(slice[offsets[1]:offsets[2]], compatible)
if err != nil {
return nil, err
}

_, err = ScriptFromSlice(slice[offsets[2]:offsets[3]], compatible)
if err != nil {
return nil, err
}

return &OffChainParticipant{inner: slice}, nil
}

func (s *OffChainParticipant) TotalSize() uint {
return uint(unpackNumber(s.inner))
}
func (s *OffChainParticipant) FieldCount() uint {
var number uint = 0
if uint32(s.TotalSize()) == HeaderSizeUint {
return number
}
number = uint(unpackNumber(s.inner[HeaderSizeUint:]))/4 - 1
return number
}
func (s *OffChainParticipant) Len() uint {
return s.FieldCount()
}
func (s *OffChainParticipant) IsEmpty() bool {
return s.Len() == 0
}
func (s *OffChainParticipant) CountExtraFields() uint {
return s.FieldCount() - 3
}

func (s *OffChainParticipant) HasExtraFields() bool {
return 3 != s.FieldCount()
}

func (s *OffChainParticipant) PubKey() *SEC1EncodedPubKey {
start := unpackNumber(s.inner[4:])
end := unpackNumber(s.inner[8:])
return SEC1EncodedPubKeyFromSliceUnchecked(s.inner[start:end])
}

func (s *OffChainParticipant) PaymentScript() *Script {
start := unpackNumber(s.inner[8:])
end := unpackNumber(s.inner[12:])
return ScriptFromSliceUnchecked(s.inner[start:end])
}

func (s *OffChainParticipant) UnlockScript() *Script {
var ret *Script
start := unpackNumber(s.inner[12:])
if s.HasExtraFields() {
end := unpackNumber(s.inner[16:])
ret = ScriptFromSliceUnchecked(s.inner[start:end])
} else {
ret = ScriptFromSliceUnchecked(s.inner[start:])
}
return ret
}

func (s *OffChainParticipant) AsBuilder() OffChainParticipantBuilder {
ret := NewOffChainParticipantBuilder().PubKey(*s.PubKey()).PaymentScript(*s.PaymentScript()).UnlockScript(*s.UnlockScript())
return *ret
}
Loading