complete transfer v1 -> v1
This commit is contained in:
parent
3a9d132f8d
commit
3ab2b57835
@ -478,7 +478,7 @@ func (*NockchainNamedSpend_Witness) isNockchainNamedSpend_SpendKind() {}
|
||||
type NockchainSpendV0 struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Signatures []*NockchainSignature `protobuf:"bytes,1,rep,name=signatures,proto3" json:"signatures,omitempty"`
|
||||
Seeds []*NockchainSeedV0 `protobuf:"bytes,2,rep,name=seeds,proto3" json:"seeds,omitempty"`
|
||||
Seeds []*NockchainSeed `protobuf:"bytes,2,rep,name=seeds,proto3" json:"seeds,omitempty"`
|
||||
Fee uint64 `protobuf:"varint,3,opt,name=fee,proto3" json:"fee,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
@ -521,7 +521,7 @@ func (x *NockchainSpendV0) GetSignatures() []*NockchainSignature {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NockchainSpendV0) GetSeeds() []*NockchainSeedV0 {
|
||||
func (x *NockchainSpendV0) GetSeeds() []*NockchainSeed {
|
||||
if x != nil {
|
||||
return x.Seeds
|
||||
}
|
||||
@ -537,6 +537,9 @@ func (x *NockchainSpendV0) GetFee() uint64 {
|
||||
|
||||
type NockchainSpendV1 struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Witness []*NockchainWitness `protobuf:"bytes,1,rep,name=witness,proto3" json:"witness,omitempty"`
|
||||
Seeds []*NockchainSeed `protobuf:"bytes,2,rep,name=seeds,proto3" json:"seeds,omitempty"`
|
||||
Fee uint64 `protobuf:"varint,3,opt,name=fee,proto3" json:"fee,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@ -571,6 +574,27 @@ func (*NockchainSpendV1) Descriptor() ([]byte, []int) {
|
||||
return file_types_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
func (x *NockchainSpendV1) GetWitness() []*NockchainWitness {
|
||||
if x != nil {
|
||||
return x.Witness
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NockchainSpendV1) GetSeeds() []*NockchainSeed {
|
||||
if x != nil {
|
||||
return x.Seeds
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NockchainSpendV1) GetFee() uint64 {
|
||||
if x != nil {
|
||||
return x.Fee
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type NockchainNote struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Types that are valid to be assigned to Note:
|
||||
@ -658,9 +682,9 @@ type NockchainNoteV0 struct {
|
||||
Version Version `protobuf:"varint,1,opt,name=version,proto3,enum=nockchain.public.v2.Version" json:"version,omitempty"`
|
||||
OriginPage uint64 `protobuf:"varint,2,opt,name=origin_page,json=originPage,proto3" json:"origin_page,omitempty"`
|
||||
Name *NockchainName `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Lock *NockchainLock `protobuf:"bytes,5,opt,name=lock,proto3" json:"lock,omitempty"`
|
||||
Source *NockchainSource `protobuf:"bytes,6,opt,name=source,proto3" json:"source,omitempty"`
|
||||
Asset uint64 `protobuf:"varint,7,opt,name=asset,proto3" json:"asset,omitempty"`
|
||||
Lock *NockchainLock `protobuf:"bytes,4,opt,name=lock,proto3" json:"lock,omitempty"`
|
||||
Source *NockchainSource `protobuf:"bytes,5,opt,name=source,proto3" json:"source,omitempty"`
|
||||
Asset uint64 `protobuf:"varint,6,opt,name=asset,proto3" json:"asset,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@ -739,6 +763,11 @@ func (x *NockchainNoteV0) GetAsset() uint64 {
|
||||
|
||||
type NockchainNoteV1 struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Version Version `protobuf:"varint,1,opt,name=version,proto3,enum=nockchain.public.v2.Version" json:"version,omitempty"`
|
||||
OriginPage uint64 `protobuf:"varint,2,opt,name=origin_page,json=originPage,proto3" json:"origin_page,omitempty"`
|
||||
Name *NockchainName `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
|
||||
NoteData *NockchainLock `protobuf:"bytes,4,opt,name=note_data,json=noteData,proto3" json:"note_data,omitempty"`
|
||||
Assets uint64 `protobuf:"varint,5,opt,name=assets,proto3" json:"assets,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@ -773,6 +802,41 @@ func (*NockchainNoteV1) Descriptor() ([]byte, []int) {
|
||||
return file_types_proto_rawDescGZIP(), []int{10}
|
||||
}
|
||||
|
||||
func (x *NockchainNoteV1) GetVersion() Version {
|
||||
if x != nil {
|
||||
return x.Version
|
||||
}
|
||||
return Version_V0
|
||||
}
|
||||
|
||||
func (x *NockchainNoteV1) GetOriginPage() uint64 {
|
||||
if x != nil {
|
||||
return x.OriginPage
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NockchainNoteV1) GetName() *NockchainName {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NockchainNoteV1) GetNoteData() *NockchainLock {
|
||||
if x != nil {
|
||||
return x.NoteData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NockchainNoteV1) GetAssets() uint64 {
|
||||
if x != nil {
|
||||
return x.Assets
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type NockchainName struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
First string `protobuf:"bytes,1,opt,name=first,proto3" json:"first,omitempty"`
|
||||
@ -885,31 +949,28 @@ func (x *NockchainSignature) GetSig() []uint64 {
|
||||
return nil
|
||||
}
|
||||
|
||||
type NockchainSeedV0 struct {
|
||||
type NockchainWitness struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
OutputSource *NockchainSource `protobuf:"bytes,1,opt,name=output_source,json=outputSource,proto3,oneof" json:"output_source,omitempty"`
|
||||
LockRoot string `protobuf:"bytes,2,opt,name=lock_root,json=lockRoot,proto3" json:"lock_root,omitempty"`
|
||||
NoteData *NockchainLock `protobuf:"bytes,3,opt,name=note_data,json=noteData,proto3" json:"note_data,omitempty"`
|
||||
Gift uint64 `protobuf:"varint,4,opt,name=gift,proto3" json:"gift,omitempty"`
|
||||
ParentHash string `protobuf:"bytes,5,opt,name=parent_hash,json=parentHash,proto3" json:"parent_hash,omitempty"`
|
||||
Lmp *NockchainLockMerkleProof `protobuf:"bytes,1,opt,name=lmp,proto3" json:"lmp,omitempty"`
|
||||
Pkh []*NockchainSignature `protobuf:"bytes,2,rep,name=pkh,proto3" json:"pkh,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *NockchainSeedV0) Reset() {
|
||||
*x = NockchainSeedV0{}
|
||||
func (x *NockchainWitness) Reset() {
|
||||
*x = NockchainWitness{}
|
||||
mi := &file_types_proto_msgTypes[13]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *NockchainSeedV0) String() string {
|
||||
func (x *NockchainWitness) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*NockchainSeedV0) ProtoMessage() {}
|
||||
func (*NockchainWitness) ProtoMessage() {}
|
||||
|
||||
func (x *NockchainSeedV0) ProtoReflect() protoreflect.Message {
|
||||
func (x *NockchainWitness) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_types_proto_msgTypes[13]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
@ -921,40 +982,155 @@ func (x *NockchainSeedV0) ProtoReflect() protoreflect.Message {
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use NockchainSeedV0.ProtoReflect.Descriptor instead.
|
||||
func (*NockchainSeedV0) Descriptor() ([]byte, []int) {
|
||||
// Deprecated: Use NockchainWitness.ProtoReflect.Descriptor instead.
|
||||
func (*NockchainWitness) Descriptor() ([]byte, []int) {
|
||||
return file_types_proto_rawDescGZIP(), []int{13}
|
||||
}
|
||||
|
||||
func (x *NockchainSeedV0) GetOutputSource() *NockchainSource {
|
||||
func (x *NockchainWitness) GetLmp() *NockchainLockMerkleProof {
|
||||
if x != nil {
|
||||
return x.Lmp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NockchainWitness) GetPkh() []*NockchainSignature {
|
||||
if x != nil {
|
||||
return x.Pkh
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type NockchainLockMerkleProof struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
SpendCondition *NockchainLock `protobuf:"bytes,1,opt,name=spend_condition,json=spendCondition,proto3" json:"spend_condition,omitempty"`
|
||||
Axis uint64 `protobuf:"varint,2,opt,name=axis,proto3" json:"axis,omitempty"`
|
||||
MerkleRoot string `protobuf:"bytes,3,opt,name=merkle_root,json=merkleRoot,proto3" json:"merkle_root,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *NockchainLockMerkleProof) Reset() {
|
||||
*x = NockchainLockMerkleProof{}
|
||||
mi := &file_types_proto_msgTypes[14]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *NockchainLockMerkleProof) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*NockchainLockMerkleProof) ProtoMessage() {}
|
||||
|
||||
func (x *NockchainLockMerkleProof) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_types_proto_msgTypes[14]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use NockchainLockMerkleProof.ProtoReflect.Descriptor instead.
|
||||
func (*NockchainLockMerkleProof) Descriptor() ([]byte, []int) {
|
||||
return file_types_proto_rawDescGZIP(), []int{14}
|
||||
}
|
||||
|
||||
func (x *NockchainLockMerkleProof) GetSpendCondition() *NockchainLock {
|
||||
if x != nil {
|
||||
return x.SpendCondition
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NockchainLockMerkleProof) GetAxis() uint64 {
|
||||
if x != nil {
|
||||
return x.Axis
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NockchainLockMerkleProof) GetMerkleRoot() string {
|
||||
if x != nil {
|
||||
return x.MerkleRoot
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type NockchainSeed struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
OutputSource *NockchainSource `protobuf:"bytes,1,opt,name=output_source,json=outputSource,proto3,oneof" json:"output_source,omitempty"`
|
||||
LockRoot string `protobuf:"bytes,2,opt,name=lock_root,json=lockRoot,proto3" json:"lock_root,omitempty"`
|
||||
NoteData *NockchainLock `protobuf:"bytes,3,opt,name=note_data,json=noteData,proto3" json:"note_data,omitempty"`
|
||||
Gift uint64 `protobuf:"varint,4,opt,name=gift,proto3" json:"gift,omitempty"`
|
||||
ParentHash string `protobuf:"bytes,5,opt,name=parent_hash,json=parentHash,proto3" json:"parent_hash,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *NockchainSeed) Reset() {
|
||||
*x = NockchainSeed{}
|
||||
mi := &file_types_proto_msgTypes[15]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *NockchainSeed) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*NockchainSeed) ProtoMessage() {}
|
||||
|
||||
func (x *NockchainSeed) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_types_proto_msgTypes[15]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use NockchainSeed.ProtoReflect.Descriptor instead.
|
||||
func (*NockchainSeed) Descriptor() ([]byte, []int) {
|
||||
return file_types_proto_rawDescGZIP(), []int{15}
|
||||
}
|
||||
|
||||
func (x *NockchainSeed) GetOutputSource() *NockchainSource {
|
||||
if x != nil {
|
||||
return x.OutputSource
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NockchainSeedV0) GetLockRoot() string {
|
||||
func (x *NockchainSeed) GetLockRoot() string {
|
||||
if x != nil {
|
||||
return x.LockRoot
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *NockchainSeedV0) GetNoteData() *NockchainLock {
|
||||
func (x *NockchainSeed) GetNoteData() *NockchainLock {
|
||||
if x != nil {
|
||||
return x.NoteData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NockchainSeedV0) GetGift() uint64 {
|
||||
func (x *NockchainSeed) GetGift() uint64 {
|
||||
if x != nil {
|
||||
return x.Gift
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NockchainSeedV0) GetParentHash() string {
|
||||
func (x *NockchainSeed) GetParentHash() string {
|
||||
if x != nil {
|
||||
return x.ParentHash
|
||||
}
|
||||
@ -971,7 +1147,7 @@ type NockchainLock struct {
|
||||
|
||||
func (x *NockchainLock) Reset() {
|
||||
*x = NockchainLock{}
|
||||
mi := &file_types_proto_msgTypes[14]
|
||||
mi := &file_types_proto_msgTypes[16]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@ -983,7 +1159,7 @@ func (x *NockchainLock) String() string {
|
||||
func (*NockchainLock) ProtoMessage() {}
|
||||
|
||||
func (x *NockchainLock) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_types_proto_msgTypes[14]
|
||||
mi := &file_types_proto_msgTypes[16]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@ -996,7 +1172,7 @@ func (x *NockchainLock) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use NockchainLock.ProtoReflect.Descriptor instead.
|
||||
func (*NockchainLock) Descriptor() ([]byte, []int) {
|
||||
return file_types_proto_rawDescGZIP(), []int{14}
|
||||
return file_types_proto_rawDescGZIP(), []int{16}
|
||||
}
|
||||
|
||||
func (x *NockchainLock) GetKeysRequired() uint64 {
|
||||
@ -1023,7 +1199,7 @@ type NockchainSource struct {
|
||||
|
||||
func (x *NockchainSource) Reset() {
|
||||
*x = NockchainSource{}
|
||||
mi := &file_types_proto_msgTypes[15]
|
||||
mi := &file_types_proto_msgTypes[17]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@ -1035,7 +1211,7 @@ func (x *NockchainSource) String() string {
|
||||
func (*NockchainSource) ProtoMessage() {}
|
||||
|
||||
func (x *NockchainSource) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_types_proto_msgTypes[15]
|
||||
mi := &file_types_proto_msgTypes[17]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@ -1048,7 +1224,7 @@ func (x *NockchainSource) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use NockchainSource.ProtoReflect.Descriptor instead.
|
||||
func (*NockchainSource) Descriptor() ([]byte, []int) {
|
||||
return file_types_proto_rawDescGZIP(), []int{15}
|
||||
return file_types_proto_rawDescGZIP(), []int{17}
|
||||
}
|
||||
|
||||
func (x *NockchainSource) GetSource() string {
|
||||
@ -1094,14 +1270,17 @@ const file_types_proto_rawDesc = "" +
|
||||
"\x06legacy\x18\x02 \x01(\v2%.nockchain.public.v2.NockchainSpendV0H\x00R\x06legacy\x12A\n" +
|
||||
"\awitness\x18\x03 \x01(\v2%.nockchain.public.v2.NockchainSpendV1H\x00R\awitnessB\f\n" +
|
||||
"\n" +
|
||||
"spend_kind\"\xa9\x01\n" +
|
||||
"spend_kind\"\xa7\x01\n" +
|
||||
"\x10NockchainSpendV0\x12G\n" +
|
||||
"\n" +
|
||||
"signatures\x18\x01 \x03(\v2'.nockchain.public.v2.NockchainSignatureR\n" +
|
||||
"signatures\x12:\n" +
|
||||
"\x05seeds\x18\x02 \x03(\v2$.nockchain.public.v2.NockchainSeedV0R\x05seeds\x12\x10\n" +
|
||||
"\x03fee\x18\x03 \x01(\x04R\x03fee\"\x12\n" +
|
||||
"\x10NockchainSpendV1\"\x87\x01\n" +
|
||||
"signatures\x128\n" +
|
||||
"\x05seeds\x18\x02 \x03(\v2\".nockchain.public.v2.NockchainSeedR\x05seeds\x12\x10\n" +
|
||||
"\x03fee\x18\x03 \x01(\x04R\x03fee\"\x9f\x01\n" +
|
||||
"\x10NockchainSpendV1\x12?\n" +
|
||||
"\awitness\x18\x01 \x03(\v2%.nockchain.public.v2.NockchainWitnessR\awitness\x128\n" +
|
||||
"\x05seeds\x18\x02 \x03(\v2\".nockchain.public.v2.NockchainSeedR\x05seeds\x12\x10\n" +
|
||||
"\x03fee\x18\x03 \x01(\x04R\x03fee\"\x87\x01\n" +
|
||||
"\rNockchainNote\x126\n" +
|
||||
"\x02v0\x18\x01 \x01(\v2$.nockchain.public.v2.NockchainNoteV0H\x00R\x02v0\x126\n" +
|
||||
"\x02v1\x18\x02 \x01(\v2$.nockchain.public.v2.NockchainNoteV1H\x00R\x02v1B\x06\n" +
|
||||
@ -1111,18 +1290,32 @@ const file_types_proto_rawDesc = "" +
|
||||
"\vorigin_page\x18\x02 \x01(\x04R\n" +
|
||||
"originPage\x126\n" +
|
||||
"\x04name\x18\x03 \x01(\v2\".nockchain.public.v2.NockchainNameR\x04name\x126\n" +
|
||||
"\x04lock\x18\x05 \x01(\v2\".nockchain.public.v2.NockchainLockR\x04lock\x12<\n" +
|
||||
"\x06source\x18\x06 \x01(\v2$.nockchain.public.v2.NockchainSourceR\x06source\x12\x14\n" +
|
||||
"\x05asset\x18\a \x01(\x04R\x05asset\"\x11\n" +
|
||||
"\x0fNockchainNoteV1\"9\n" +
|
||||
"\x04lock\x18\x04 \x01(\v2\".nockchain.public.v2.NockchainLockR\x04lock\x12<\n" +
|
||||
"\x06source\x18\x05 \x01(\v2$.nockchain.public.v2.NockchainSourceR\x06source\x12\x14\n" +
|
||||
"\x05asset\x18\x06 \x01(\x04R\x05asset\"\xfb\x01\n" +
|
||||
"\x0fNockchainNoteV1\x126\n" +
|
||||
"\aversion\x18\x01 \x01(\x0e2\x1c.nockchain.public.v2.VersionR\aversion\x12\x1f\n" +
|
||||
"\vorigin_page\x18\x02 \x01(\x04R\n" +
|
||||
"originPage\x126\n" +
|
||||
"\x04name\x18\x03 \x01(\v2\".nockchain.public.v2.NockchainNameR\x04name\x12?\n" +
|
||||
"\tnote_data\x18\x04 \x01(\v2\".nockchain.public.v2.NockchainLockR\bnoteData\x12\x16\n" +
|
||||
"\x06assets\x18\x05 \x01(\x04R\x06assets\"9\n" +
|
||||
"\rNockchainName\x12\x14\n" +
|
||||
"\x05first\x18\x01 \x01(\tR\x05first\x12\x12\n" +
|
||||
"\x04last\x18\x02 \x01(\tR\x04last\"R\n" +
|
||||
"\x12NockchainSignature\x12\x16\n" +
|
||||
"\x06pubkey\x18\x01 \x01(\tR\x06pubkey\x12\x12\n" +
|
||||
"\x04chal\x18\x02 \x03(\x04R\x04chal\x12\x10\n" +
|
||||
"\x03sig\x18\x03 \x03(\x04R\x03sig\"\x86\x02\n" +
|
||||
"\x0fNockchainSeedV0\x12N\n" +
|
||||
"\x03sig\x18\x03 \x03(\x04R\x03sig\"\x8e\x01\n" +
|
||||
"\x10NockchainWitness\x12?\n" +
|
||||
"\x03lmp\x18\x01 \x01(\v2-.nockchain.public.v2.NockchainLockMerkleProofR\x03lmp\x129\n" +
|
||||
"\x03pkh\x18\x02 \x03(\v2'.nockchain.public.v2.NockchainSignatureR\x03pkh\"\x9c\x01\n" +
|
||||
"\x18NockchainLockMerkleProof\x12K\n" +
|
||||
"\x0fspend_condition\x18\x01 \x01(\v2\".nockchain.public.v2.NockchainLockR\x0espendCondition\x12\x12\n" +
|
||||
"\x04axis\x18\x02 \x01(\x04R\x04axis\x12\x1f\n" +
|
||||
"\vmerkle_root\x18\x03 \x01(\tR\n" +
|
||||
"merkleRoot\"\x84\x02\n" +
|
||||
"\rNockchainSeed\x12N\n" +
|
||||
"\routput_source\x18\x01 \x01(\v2$.nockchain.public.v2.NockchainSourceH\x00R\foutputSource\x88\x01\x01\x12\x1b\n" +
|
||||
"\tlock_root\x18\x02 \x01(\tR\blockRoot\x12?\n" +
|
||||
"\tnote_data\x18\x03 \x01(\v2\".nockchain.public.v2.NockchainLockR\bnoteData\x12\x12\n" +
|
||||
@ -1164,7 +1357,7 @@ func file_types_proto_rawDescGZIP() []byte {
|
||||
}
|
||||
|
||||
var file_types_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||
var file_types_proto_msgTypes = make([]protoimpl.MessageInfo, 16)
|
||||
var file_types_proto_msgTypes = make([]protoimpl.MessageInfo, 18)
|
||||
var file_types_proto_goTypes = []any{
|
||||
(ImportType)(0), // 0: nockchain.public.v2.ImportType
|
||||
(Version)(0), // 1: nockchain.public.v2.Version
|
||||
@ -1181,13 +1374,15 @@ var file_types_proto_goTypes = []any{
|
||||
(*NockchainNoteV1)(nil), // 12: nockchain.public.v2.NockchainNoteV1
|
||||
(*NockchainName)(nil), // 13: nockchain.public.v2.NockchainName
|
||||
(*NockchainSignature)(nil), // 14: nockchain.public.v2.NockchainSignature
|
||||
(*NockchainSeedV0)(nil), // 15: nockchain.public.v2.NockchainSeedV0
|
||||
(*NockchainLock)(nil), // 16: nockchain.public.v2.NockchainLock
|
||||
(*NockchainSource)(nil), // 17: nockchain.public.v2.NockchainSource
|
||||
(*Balance)(nil), // 18: nockchain.public.v2.Balance
|
||||
(*NockchainWitness)(nil), // 15: nockchain.public.v2.NockchainWitness
|
||||
(*NockchainLockMerkleProof)(nil), // 16: nockchain.public.v2.NockchainLockMerkleProof
|
||||
(*NockchainSeed)(nil), // 17: nockchain.public.v2.NockchainSeed
|
||||
(*NockchainLock)(nil), // 18: nockchain.public.v2.NockchainLock
|
||||
(*NockchainSource)(nil), // 19: nockchain.public.v2.NockchainSource
|
||||
(*Balance)(nil), // 20: nockchain.public.v2.Balance
|
||||
}
|
||||
var file_types_proto_depIdxs = []int32{
|
||||
18, // 0: nockchain.public.v2.ScanData.data:type_name -> nockchain.public.v2.Balance
|
||||
20, // 0: nockchain.public.v2.ScanData.data:type_name -> nockchain.public.v2.Balance
|
||||
4, // 1: nockchain.public.v2.TimelockIntent.absolute:type_name -> nockchain.public.v2.TimelockRange
|
||||
4, // 2: nockchain.public.v2.TimelockIntent.relative:type_name -> nockchain.public.v2.TimelockRange
|
||||
5, // 3: nockchain.public.v2.TimelockRange.min:type_name -> nockchain.public.v2.Timelock
|
||||
@ -1198,20 +1393,28 @@ var file_types_proto_depIdxs = []int32{
|
||||
8, // 8: nockchain.public.v2.NockchainNamedSpend.legacy:type_name -> nockchain.public.v2.NockchainSpendV0
|
||||
9, // 9: nockchain.public.v2.NockchainNamedSpend.witness:type_name -> nockchain.public.v2.NockchainSpendV1
|
||||
14, // 10: nockchain.public.v2.NockchainSpendV0.signatures:type_name -> nockchain.public.v2.NockchainSignature
|
||||
15, // 11: nockchain.public.v2.NockchainSpendV0.seeds:type_name -> nockchain.public.v2.NockchainSeedV0
|
||||
11, // 12: nockchain.public.v2.NockchainNote.v0:type_name -> nockchain.public.v2.NockchainNoteV0
|
||||
12, // 13: nockchain.public.v2.NockchainNote.v1:type_name -> nockchain.public.v2.NockchainNoteV1
|
||||
1, // 14: nockchain.public.v2.NockchainNoteV0.version:type_name -> nockchain.public.v2.Version
|
||||
13, // 15: nockchain.public.v2.NockchainNoteV0.name:type_name -> nockchain.public.v2.NockchainName
|
||||
16, // 16: nockchain.public.v2.NockchainNoteV0.lock:type_name -> nockchain.public.v2.NockchainLock
|
||||
17, // 17: nockchain.public.v2.NockchainNoteV0.source:type_name -> nockchain.public.v2.NockchainSource
|
||||
17, // 18: nockchain.public.v2.NockchainSeedV0.output_source:type_name -> nockchain.public.v2.NockchainSource
|
||||
16, // 19: nockchain.public.v2.NockchainSeedV0.note_data:type_name -> nockchain.public.v2.NockchainLock
|
||||
20, // [20:20] is the sub-list for method output_type
|
||||
20, // [20:20] is the sub-list for method input_type
|
||||
20, // [20:20] is the sub-list for extension type_name
|
||||
20, // [20:20] is the sub-list for extension extendee
|
||||
0, // [0:20] is the sub-list for field type_name
|
||||
17, // 11: nockchain.public.v2.NockchainSpendV0.seeds:type_name -> nockchain.public.v2.NockchainSeed
|
||||
15, // 12: nockchain.public.v2.NockchainSpendV1.witness:type_name -> nockchain.public.v2.NockchainWitness
|
||||
17, // 13: nockchain.public.v2.NockchainSpendV1.seeds:type_name -> nockchain.public.v2.NockchainSeed
|
||||
11, // 14: nockchain.public.v2.NockchainNote.v0:type_name -> nockchain.public.v2.NockchainNoteV0
|
||||
12, // 15: nockchain.public.v2.NockchainNote.v1:type_name -> nockchain.public.v2.NockchainNoteV1
|
||||
1, // 16: nockchain.public.v2.NockchainNoteV0.version:type_name -> nockchain.public.v2.Version
|
||||
13, // 17: nockchain.public.v2.NockchainNoteV0.name:type_name -> nockchain.public.v2.NockchainName
|
||||
18, // 18: nockchain.public.v2.NockchainNoteV0.lock:type_name -> nockchain.public.v2.NockchainLock
|
||||
19, // 19: nockchain.public.v2.NockchainNoteV0.source:type_name -> nockchain.public.v2.NockchainSource
|
||||
1, // 20: nockchain.public.v2.NockchainNoteV1.version:type_name -> nockchain.public.v2.Version
|
||||
13, // 21: nockchain.public.v2.NockchainNoteV1.name:type_name -> nockchain.public.v2.NockchainName
|
||||
18, // 22: nockchain.public.v2.NockchainNoteV1.note_data:type_name -> nockchain.public.v2.NockchainLock
|
||||
16, // 23: nockchain.public.v2.NockchainWitness.lmp:type_name -> nockchain.public.v2.NockchainLockMerkleProof
|
||||
14, // 24: nockchain.public.v2.NockchainWitness.pkh:type_name -> nockchain.public.v2.NockchainSignature
|
||||
18, // 25: nockchain.public.v2.NockchainLockMerkleProof.spend_condition:type_name -> nockchain.public.v2.NockchainLock
|
||||
19, // 26: nockchain.public.v2.NockchainSeed.output_source:type_name -> nockchain.public.v2.NockchainSource
|
||||
18, // 27: nockchain.public.v2.NockchainSeed.note_data:type_name -> nockchain.public.v2.NockchainLock
|
||||
28, // [28:28] is the sub-list for method output_type
|
||||
28, // [28:28] is the sub-list for method input_type
|
||||
28, // [28:28] is the sub-list for extension type_name
|
||||
28, // [28:28] is the sub-list for extension extendee
|
||||
0, // [0:28] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_types_proto_init() }
|
||||
@ -1230,14 +1433,14 @@ func file_types_proto_init() {
|
||||
(*NockchainNote_V0)(nil),
|
||||
(*NockchainNote_V1)(nil),
|
||||
}
|
||||
file_types_proto_msgTypes[13].OneofWrappers = []any{}
|
||||
file_types_proto_msgTypes[15].OneofWrappers = []any{}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_types_proto_rawDesc), len(file_types_proto_rawDesc)),
|
||||
NumEnums: 2,
|
||||
NumMessages: 16,
|
||||
NumMessages: 18,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
|
||||
@ -46,11 +46,14 @@ message NockchainNamedSpend {
|
||||
|
||||
message NockchainSpendV0 {
|
||||
repeated NockchainSignature signatures = 1;
|
||||
repeated NockchainSeedV0 seeds = 2;
|
||||
repeated NockchainSeed seeds = 2;
|
||||
uint64 fee = 3;
|
||||
}
|
||||
|
||||
message NockchainSpendV1 {
|
||||
repeated NockchainWitness witness = 1;
|
||||
repeated NockchainSeed seeds = 2;
|
||||
uint64 fee = 3;
|
||||
}
|
||||
|
||||
message NockchainNote {
|
||||
@ -63,12 +66,17 @@ message NockchainNoteV0 {
|
||||
Version version = 1;
|
||||
uint64 origin_page = 2;
|
||||
NockchainName name = 3;
|
||||
NockchainLock lock = 5;
|
||||
NockchainSource source = 6;
|
||||
uint64 asset =7;
|
||||
NockchainLock lock = 4;
|
||||
NockchainSource source = 5;
|
||||
uint64 asset =6;
|
||||
}
|
||||
|
||||
message NockchainNoteV1 {
|
||||
Version version = 1;
|
||||
uint64 origin_page = 2;
|
||||
NockchainName name = 3;
|
||||
NockchainLock note_data = 4;
|
||||
uint64 assets = 5;
|
||||
}
|
||||
|
||||
message NockchainName {
|
||||
@ -82,7 +90,18 @@ message NockchainSignature {
|
||||
repeated uint64 sig = 3;
|
||||
}
|
||||
|
||||
message NockchainSeedV0 {
|
||||
message NockchainWitness {
|
||||
NockchainLockMerkleProof lmp = 1;
|
||||
repeated NockchainSignature pkh = 2;
|
||||
}
|
||||
|
||||
message NockchainLockMerkleProof {
|
||||
NockchainLock spend_condition = 1;
|
||||
uint64 axis = 2;
|
||||
string merkle_root = 3;
|
||||
}
|
||||
|
||||
message NockchainSeed {
|
||||
optional NockchainSource output_source = 1;
|
||||
string lock_root = 2;
|
||||
NockchainLock note_data = 3;
|
||||
|
||||
@ -9,7 +9,9 @@ import (
|
||||
"github.com/phamminh0811/private-grpc/nockchain"
|
||||
)
|
||||
|
||||
var LastName = [5]uint64{9541855607561054508, 12383849149342406623, 11220017934615522559, 678840671137489369, 8985908938884028381}
|
||||
var (
|
||||
MerkleHash = [5]uint64{7971649669803894685, 16663670492333541326, 11038715785817710450, 18178011379925321681, 17049062282971338707}
|
||||
)
|
||||
|
||||
func HashPubkey(pkPoint crypto.CheetahPoint) [5]uint64 {
|
||||
belts := []crypto.Belt{{Value: 13}}
|
||||
@ -22,7 +24,7 @@ func HashPubkey(pkPoint crypto.CheetahPoint) [5]uint64 {
|
||||
return crypto.Tip5HashBelts(belts)
|
||||
}
|
||||
|
||||
func HashSignature(signature *nockchain.NockchainSignature) ([5]uint64, error) {
|
||||
func HashSignatureV0(signature *nockchain.NockchainSignature) ([5]uint64, error) {
|
||||
belts := []crypto.Belt{{Value: 16}}
|
||||
for _, i := range signature.Chal {
|
||||
belts = append(belts, crypto.Belt{Value: i})
|
||||
@ -43,6 +45,42 @@ func HashSignature(signature *nockchain.NockchainSignature) ([5]uint64, error) {
|
||||
return crypto.Tip5RehashTenCell(sigHash, crypto.Tip5ZeroZero), nil
|
||||
}
|
||||
|
||||
func HashSignatureV1(signature *nockchain.NockchainSignature) ([5]uint64, error) {
|
||||
belts := []crypto.Belt{{Value: 16}}
|
||||
for _, i := range signature.Chal {
|
||||
belts = append(belts, crypto.Belt{Value: i})
|
||||
}
|
||||
for _, i := range signature.Sig {
|
||||
belts = append(belts, crypto.Belt{Value: i})
|
||||
}
|
||||
for _, i := range crypto.MagicDyckForT8 {
|
||||
belts = append(belts, crypto.Belt{Value: i})
|
||||
}
|
||||
sigHash := crypto.Tip5HashBelts(belts)
|
||||
pkPoint, err := crypto.CheetaPointFromBytes(base58.Decode(signature.Pubkey))
|
||||
if err != nil {
|
||||
return [5]uint64{}, err
|
||||
}
|
||||
pkHash := HashPubkey(pkPoint)
|
||||
sigHash = crypto.Tip5RehashTenCell(pkHash, sigHash)
|
||||
pkHashSig := crypto.Tip5RehashTenCell(pkHash, sigHash)
|
||||
return crypto.Tip5RehashTenCell(pkHashSig, crypto.Tip5ZeroZero), nil
|
||||
}
|
||||
func HashWitness(witness *nockchain.NockchainWitness) ([5]uint64, error) {
|
||||
spendConditionHash := HashLock(witness.Lmp.SpendCondition)
|
||||
rootHash := crypto.Base58ToTip5Hash(witness.Lmp.MerkleRoot)
|
||||
rootHashZero := crypto.Tip5RehashTenCell(rootHash, crypto.Tip5Zero)
|
||||
axisHashRoot := crypto.Tip5RehashTenCell(MerkleHash, rootHashZero)
|
||||
lmpHash := crypto.Tip5RehashTenCell(spendConditionHash, axisHashRoot)
|
||||
|
||||
sigHash, err := HashSignatureV1(witness.Pkh[0])
|
||||
if err != nil {
|
||||
return [5]uint64{}, err
|
||||
}
|
||||
sigHashZeroZero := crypto.Tip5RehashTenCell(sigHash, crypto.Tip5ZeroZero)
|
||||
return crypto.Tip5RehashTenCell(lmpHash, sigHashZeroZero), nil
|
||||
}
|
||||
|
||||
func HashNoteData(lock *nockchain.NockchainLock) [5]uint64 {
|
||||
keysRequiredHash := crypto.Tip5HashLeaf(lock.KeysRequired)
|
||||
// TODO: handle multisig
|
||||
@ -67,9 +105,10 @@ func HashOwner(pkPoint crypto.CheetahPoint) [5]uint64 {
|
||||
return crypto.Tip5RehashTenCell(crypto.Tip5One, pkHashedZeroZero)
|
||||
}
|
||||
|
||||
func NockName(ownerHash [5]uint64) ([5]uint64, [5]uint64) {
|
||||
firstName := first(ownerHash)
|
||||
return firstName, LastName
|
||||
func NockFirstName(ownerHash [5]uint64) [5]uint64 {
|
||||
ownerHashZero := crypto.Tip5RehashTenCell(ownerHash, crypto.Tip5Zero)
|
||||
ownerHashZeroOne := crypto.Tip5RehashTenCell(crypto.Tip5One, ownerHashZero)
|
||||
return crypto.Tip5RehashTenCell(crypto.Tip5Zero, ownerHashZeroOne)
|
||||
}
|
||||
|
||||
func HashName(name *nockchain.NockchainName) [5]uint64 {
|
||||
@ -117,6 +156,19 @@ func HashNoteV0(note *nockchain.NockchainNoteV0) ([5]uint64, error) {
|
||||
return crypto.Tip5RehashTenCell(p, q), nil
|
||||
}
|
||||
|
||||
func HashNoteV1(note *nockchain.NockchainNoteV1) [5]uint64 {
|
||||
versionHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: uint64(note.Version)}})
|
||||
blockHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: note.OriginPage}})
|
||||
nameHash := HashName(note.Name)
|
||||
noteDataHash := HashNoteData(note.NoteData)
|
||||
assetHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: uint64(note.Assets)}})
|
||||
|
||||
hashNoteDataAsset := crypto.Tip5RehashTenCell(noteDataHash, assetHash)
|
||||
hashNameNoteDataAsset := crypto.Tip5RehashTenCell(nameHash, hashNoteDataAsset)
|
||||
q := crypto.Tip5RehashTenCell(blockHash, hashNameNoteDataAsset)
|
||||
return crypto.Tip5RehashTenCell(versionHash, q)
|
||||
}
|
||||
|
||||
func HashTimelockIntent(timelock *nockchain.TimelockIntent) [5]uint64 {
|
||||
if timelock == nil {
|
||||
return crypto.Tip5Zero
|
||||
@ -201,29 +253,26 @@ func HashSource(source *nockchain.NockchainSource) [5]uint64 {
|
||||
return crypto.Tip5RehashTenCell(sourceHash, crypto.Tip5One)
|
||||
}
|
||||
|
||||
func HashSeedWithoutSource(seed *nockchain.NockchainSeedV0) [5]uint64 {
|
||||
func HashSeedWithoutSource(seed *nockchain.NockchainSeed) [5]uint64 {
|
||||
lockRoot := crypto.Base58ToTip5Hash(seed.LockRoot)
|
||||
fmt.Println("lockRoot:", lockRoot)
|
||||
assetHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: seed.Gift}})
|
||||
|
||||
parentHash := crypto.Base58ToTip5Hash(seed.ParentHash)
|
||||
fmt.Println("parentHash:", parentHash)
|
||||
assetHashparentHash := crypto.Tip5RehashTenCell(assetHash, parentHash)
|
||||
|
||||
noteDataHash := HashNoteData(seed.NoteData)
|
||||
fmt.Println("noteDataHash:", noteDataHash)
|
||||
noteDataHashAssetParentHash := crypto.Tip5RehashTenCell(noteDataHash, assetHashparentHash)
|
||||
|
||||
seedHash := crypto.Tip5RehashTenCell(lockRoot, noteDataHashAssetParentHash)
|
||||
return seedHash
|
||||
}
|
||||
func HashSeed(seed *nockchain.NockchainSeedV0) [5]uint64 {
|
||||
func HashSeed(seed *nockchain.NockchainSeed) [5]uint64 {
|
||||
seedHash := HashSeedWithoutSource(seed)
|
||||
sourceHash := HashSource(seed.OutputSource)
|
||||
return crypto.Tip5RehashTenCell(sourceHash, seedHash)
|
||||
}
|
||||
|
||||
func HashSeedVarLen(seed *nockchain.NockchainSeedV0) [5]uint64 {
|
||||
func HashSeedVarLen(seed *nockchain.NockchainSeed) [5]uint64 {
|
||||
belts := []crypto.Belt{{Value: 0}}
|
||||
lockRoot := crypto.Base58ToTip5Hash(seed.LockRoot)
|
||||
for _, i := range lockRoot {
|
||||
@ -284,85 +333,91 @@ func HashSpendV0(spend *nockchain.NockchainSpendV0) ([5]uint64, error) {
|
||||
return [5]uint64{}, fmt.Errorf("signatures can not be empty")
|
||||
}
|
||||
|
||||
sigHash, err := HashSignature(spend.Signatures[0])
|
||||
sigHash, err := HashSignatureV0(spend.Signatures[0])
|
||||
if err != nil {
|
||||
return [5]uint64{}, err
|
||||
}
|
||||
|
||||
seedsTree := NewZTree(
|
||||
func(i interface{}) [5]uint64 {
|
||||
if seed, ok := i.(*nockchain.NockchainSeedV0); ok {
|
||||
return HashSeedVarLen(seed)
|
||||
} else {
|
||||
return [5]uint64{}
|
||||
}
|
||||
},
|
||||
func(i interface{}) ([5]uint64, error) {
|
||||
if seed, ok := i.(*nockchain.NockchainSeedV0); ok {
|
||||
return HashSeedWithoutSource(seed), nil
|
||||
} else {
|
||||
return [5]uint64{}, fmt.Errorf("invalid input type")
|
||||
}
|
||||
},
|
||||
)
|
||||
for _, seed := range spend.Seeds {
|
||||
seedsTree.Insert(seed, seed)
|
||||
}
|
||||
finalSeedHash, err := seedsTree.Hash()
|
||||
seedHashFee, err := HashSeedsAndFee(spend.Seeds, spend.Fee)
|
||||
if err != nil {
|
||||
return [5]uint64{}, err
|
||||
}
|
||||
|
||||
feeHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: spend.Fee}})
|
||||
seedHashFee := crypto.Tip5RehashTenCell(finalSeedHash, feeHash)
|
||||
return crypto.Tip5RehashTenCell(sigHash, seedHashFee), nil
|
||||
|
||||
}
|
||||
|
||||
func HashMsg(spend *nockchain.NockchainSpendV0) ([5]uint64, error) {
|
||||
func HashSpendV1(spend *nockchain.NockchainSpendV1) ([5]uint64, error) {
|
||||
if len(spend.Witness) == 0 {
|
||||
return [5]uint64{}, fmt.Errorf("witness can not be empty")
|
||||
}
|
||||
|
||||
witnessHash, err := HashWitness(spend.Witness[0])
|
||||
if err != nil {
|
||||
return [5]uint64{}, err
|
||||
}
|
||||
|
||||
seedHashFee, err := HashSeedsAndFee(spend.Seeds, spend.Fee)
|
||||
if err != nil {
|
||||
return [5]uint64{}, err
|
||||
}
|
||||
return crypto.Tip5RehashTenCell(witnessHash, seedHashFee), nil
|
||||
}
|
||||
|
||||
func HashMsg(seeds []*nockchain.NockchainSeed, fee uint64) ([5]uint64, error) {
|
||||
seedsTree := NewZTree(
|
||||
func(i interface{}) [5]uint64 {
|
||||
if seed, ok := i.(*nockchain.NockchainSeedV0); ok {
|
||||
if seed, ok := i.(*nockchain.NockchainSeed); ok {
|
||||
return HashSeedVarLen(seed)
|
||||
} else {
|
||||
return [5]uint64{}
|
||||
}
|
||||
},
|
||||
func(i interface{}) ([5]uint64, error) {
|
||||
if seed, ok := i.(*nockchain.NockchainSeedV0); ok {
|
||||
if seed, ok := i.(*nockchain.NockchainSeed); ok {
|
||||
return HashSeed(seed), nil
|
||||
} else {
|
||||
return [5]uint64{}, fmt.Errorf("invalid input type")
|
||||
}
|
||||
},
|
||||
)
|
||||
for _, seed := range spend.Seeds {
|
||||
for _, seed := range seeds {
|
||||
seedsTree.Insert(seed, seed)
|
||||
}
|
||||
finalSeedHash, err := seedsTree.Hash()
|
||||
if err != nil {
|
||||
return [5]uint64{}, err
|
||||
}
|
||||
feeHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: spend.Fee}})
|
||||
feeHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: fee}})
|
||||
return crypto.Tip5RehashTenCell(finalSeedHash, feeHash), nil
|
||||
}
|
||||
|
||||
// func HashInput(input *nockchain.NockchainInput) ([5]uint64, error) {
|
||||
// nameHash := HashName(input.Name)
|
||||
func HashSeedsAndFee(seeds []*nockchain.NockchainSeed, fee uint64) ([5]uint64, error) {
|
||||
seedsTree := NewZTree(
|
||||
func(i interface{}) [5]uint64 {
|
||||
if seed, ok := i.(*nockchain.NockchainSeed); ok {
|
||||
return HashSeedVarLen(seed)
|
||||
} else {
|
||||
return [5]uint64{}
|
||||
}
|
||||
},
|
||||
func(i interface{}) ([5]uint64, error) {
|
||||
if seed, ok := i.(*nockchain.NockchainSeed); ok {
|
||||
return HashSeedWithoutSource(seed), nil
|
||||
} else {
|
||||
return [5]uint64{}, fmt.Errorf("invalid input type")
|
||||
}
|
||||
},
|
||||
)
|
||||
for _, seed := range seeds {
|
||||
seedsTree.Insert(seed, seed)
|
||||
}
|
||||
finalSeedHash, err := seedsTree.Hash()
|
||||
if err != nil {
|
||||
return [5]uint64{}, err
|
||||
}
|
||||
|
||||
// noteHash, err := HashNote(input.Note)
|
||||
// if err != nil {
|
||||
// return [5]uint64{}, err
|
||||
|
||||
// }
|
||||
// spendHash, err := HashSpend(input.Spend)
|
||||
// if err != nil {
|
||||
// return [5]uint64{}, err
|
||||
|
||||
// }
|
||||
// hashNoteSpend := crypto.Tip5RehashTenCell(noteHash, spendHash)
|
||||
// return crypto.Tip5RehashTenCell(nameHash, hashNoteSpend), nil
|
||||
// }
|
||||
feeHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: fee}})
|
||||
return crypto.Tip5RehashTenCell(finalSeedHash, feeHash), nil
|
||||
}
|
||||
|
||||
func ComputeTxId(spends []*nockchain.NockchainNamedSpend, version uint64) ([5]uint64, error) {
|
||||
var spendHash [5]uint64
|
||||
@ -399,7 +454,37 @@ func ComputeTxId(spends []*nockchain.NockchainNamedSpend, version uint64) ([5]ui
|
||||
if err != nil {
|
||||
return [5]uint64{}, fmt.Errorf("error hashing spends: %v", err)
|
||||
}
|
||||
fmt.Println("spendHash:", spendHash)
|
||||
case 1:
|
||||
spendTree := NewZTree(
|
||||
func(i interface{}) [5]uint64 {
|
||||
if name, ok := i.(*nockchain.NockchainName); ok {
|
||||
return HashNameVarLen(name)
|
||||
} else {
|
||||
return [5]uint64{}
|
||||
}
|
||||
},
|
||||
func(i interface{}) ([5]uint64, error) {
|
||||
if spendEntry, ok := i.(*nockchain.NockchainNamedSpend); ok {
|
||||
nameHash := HashName(spendEntry.Name)
|
||||
spendV1Hash, err := HashSpendV1(spendEntry.GetWitness())
|
||||
if err != nil {
|
||||
return [5]uint64{}, fmt.Errorf("error hashing spend: %v", err)
|
||||
}
|
||||
|
||||
oneHashspend := crypto.Tip5RehashTenCell(crypto.Tip5One, spendV1Hash)
|
||||
return crypto.Tip5RehashTenCell(nameHash, oneHashspend), nil
|
||||
} else {
|
||||
return [5]uint64{}, fmt.Errorf("invalid input type")
|
||||
}
|
||||
},
|
||||
)
|
||||
for _, spend := range spends {
|
||||
spendTree.Insert(spend.Name, spend)
|
||||
}
|
||||
spendHash, err = spendTree.Hash()
|
||||
if err != nil {
|
||||
return [5]uint64{}, fmt.Errorf("error hashing spends: %v", err)
|
||||
}
|
||||
default:
|
||||
return [5]uint64{}, fmt.Errorf("unsupported version %d", version)
|
||||
}
|
||||
@ -431,9 +516,3 @@ func ComputeSig(m crypto.MasterKey, msg [5]uint64) ([8]uint64, [8]uint64, error)
|
||||
sigT8 := crypto.BigIntToT8(*sig)
|
||||
return chalT8, sigT8, nil
|
||||
}
|
||||
|
||||
func first(ownerHash [5]uint64) [5]uint64 {
|
||||
ownerHashZero := crypto.Tip5RehashTenCell(ownerHash, crypto.Tip5Zero)
|
||||
ownerHashZeroOne := crypto.Tip5RehashTenCell(crypto.Tip5One, ownerHashZero)
|
||||
return crypto.Tip5RehashTenCell(crypto.Tip5Zero, ownerHashZeroOne)
|
||||
}
|
||||
|
||||
@ -24,6 +24,16 @@ func Uint64ToBitsLSB0(x uint64) []bool {
|
||||
return bits
|
||||
}
|
||||
|
||||
func BitsToUint64LSB0(bits []bool, start, sz int) uint64 {
|
||||
var data uint64
|
||||
for i := 0; i < sz; i++ {
|
||||
if bits[start+i] {
|
||||
data |= 1 << i // LSB0: bit 0 = least significant
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func BoolsToBytesLSB0(bits []bool) []byte {
|
||||
if len(bits) == 0 {
|
||||
return nil
|
||||
@ -40,6 +50,16 @@ func BoolsToBytesLSB0(bits []bool) []byte {
|
||||
return bytes
|
||||
}
|
||||
|
||||
func BytesToBoolsLSB0(data []byte) []bool {
|
||||
bools := make([]bool, len(data)*8)
|
||||
for i, b := range data {
|
||||
for j := 0; j < 8; j++ {
|
||||
bools[i*8+j] = ((b >> j) & 1) == 1 // LSB0 order
|
||||
}
|
||||
}
|
||||
return bools
|
||||
}
|
||||
|
||||
func EncodeNoteData(noteData *nockchain.NockchainLock) []byte {
|
||||
bits := InitialBits
|
||||
|
||||
@ -89,3 +109,48 @@ func EncodeNoteData(noteData *nockchain.NockchainLock) []byte {
|
||||
bits = append(bits, []bool{true, false, false, true, false, true, false, true}...)
|
||||
return BoolsToBytesLSB0(bits)
|
||||
}
|
||||
|
||||
func DecodeNoteData(blob []byte) *nockchain.NockchainLock {
|
||||
bits := BytesToBoolsLSB0(blob)
|
||||
|
||||
start := len(InitialBits) + 1
|
||||
count := 0
|
||||
for !bits[start] {
|
||||
start += 1
|
||||
count += 1
|
||||
}
|
||||
start += 1
|
||||
numPksSz := uint64(1)
|
||||
if count > 1 {
|
||||
numPksSz = BitsToUint64LSB0(bits, start, count-1)
|
||||
start += count - 1
|
||||
}
|
||||
numPks := BitsToUint64LSB0(bits, start, int(numPksSz))
|
||||
start += int(numPksSz)
|
||||
start += 2
|
||||
pkHash := [5]uint64{}
|
||||
for i := 0; i < 5; i++ {
|
||||
if i != 4 {
|
||||
start += 2
|
||||
}
|
||||
start += 1
|
||||
count := 0
|
||||
for !bits[start] {
|
||||
start += 1
|
||||
count += 1
|
||||
}
|
||||
start += 1
|
||||
hashSz := uint64(count)
|
||||
if count > 1 {
|
||||
hashSz = BitsToUint64LSB0(bits, start, count-1) + 1<<(count-1)
|
||||
start += count - 1
|
||||
}
|
||||
hash := BitsToUint64LSB0(bits, start, int(hashSz))
|
||||
start += int(hashSz)
|
||||
pkHash[i] = hash
|
||||
}
|
||||
return &nockchain.NockchainLock{
|
||||
KeysRequired: numPks,
|
||||
Pubkeys: []string{crypto.Tip5HashToBase58(pkHash)},
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
WitnessWordsCount = 0
|
||||
WitnessWordsCount = 55
|
||||
SignatureWordsCount = 31
|
||||
SeedWordsCount = 13
|
||||
BaseFee = 1 << 15
|
||||
@ -390,32 +390,6 @@ func (h *GprcHandler) CreateTx(ctx context.Context, req *nockchain.CreateTxReque
|
||||
}
|
||||
}
|
||||
|
||||
nameTree := NewZTree(
|
||||
func(i interface{}) [5]uint64 {
|
||||
if name, ok := i.(*nockchain.NockchainName); ok {
|
||||
return HashNameVarLen(name)
|
||||
} else {
|
||||
return [5]uint64{}
|
||||
}
|
||||
},
|
||||
nil,
|
||||
)
|
||||
for _, name := range nnames {
|
||||
nameTree.Insert(name, nil)
|
||||
}
|
||||
nameList := nameTree.Tap()
|
||||
nameKeys := []string{}
|
||||
for _, nameKey := range nameList {
|
||||
name := nameKey.Key.(*nockchain.NockchainName)
|
||||
nameKeys = append(nameKeys, name.First+" "+name.Last)
|
||||
}
|
||||
indices := make([]int, len(nnames))
|
||||
for i, name := range nnames {
|
||||
if idx := slices.Index(nameKeys, name.First+" "+name.Last); idx != -1 {
|
||||
indices[idx] = i
|
||||
}
|
||||
}
|
||||
|
||||
specs := strings.Split(req.Recipients, ",")
|
||||
if len(specs) == 0 {
|
||||
return nil, fmt.Errorf("at least one output must be provided")
|
||||
@ -454,6 +428,11 @@ func (h *GprcHandler) CreateTx(ctx context.Context, req *nockchain.CreateTxReque
|
||||
}
|
||||
masterKey = &childKey
|
||||
}
|
||||
masterPkPoint, err := crypto.CheetaPointFromBytes(masterKey.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pkHash := HashPubkey(masterPkPoint)
|
||||
|
||||
recipent := &nockchain.NockchainLock{
|
||||
KeysRequired: 1,
|
||||
@ -464,23 +443,40 @@ func (h *GprcHandler) CreateTx(ctx context.Context, req *nockchain.CreateTxReque
|
||||
}
|
||||
refundAddr := req.RefundAddress
|
||||
if refundAddr == "" {
|
||||
masterPkPoint, err := crypto.CheetaPointFromBytes(masterKey.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pkHash := HashPubkey(masterPkPoint)
|
||||
refundAddr = crypto.Tip5HashToBase58(pkHash)
|
||||
}
|
||||
refundLock := &nockchain.NockchainLock{
|
||||
KeysRequired: 1,
|
||||
Pubkeys: []string{refundAddr},
|
||||
}
|
||||
|
||||
ownerLock := &nockchain.NockchainLock{
|
||||
KeysRequired: 1,
|
||||
Pubkeys: []string{crypto.Tip5HashToBase58(pkHash)},
|
||||
}
|
||||
|
||||
ownerHash := HashLock(ownerLock)
|
||||
// Scan key to get notes
|
||||
masterKeyScan, err := h.client.WalletGetBalance(&nockchain.GetBalanceRequest{
|
||||
var scanReq *nockchain.GetBalanceRequest
|
||||
switch req.Version {
|
||||
case 0:
|
||||
scanReq = &nockchain.GetBalanceRequest{
|
||||
Selector: &nockchain.GetBalanceRequest_Address{
|
||||
Address: base58.Encode(masterKey.PublicKey),
|
||||
},
|
||||
})
|
||||
}
|
||||
case 1:
|
||||
|
||||
firstName := crypto.Tip5RehashTenCell(crypto.Tip5Zero, ownerHash)
|
||||
scanReq = &nockchain.GetBalanceRequest{
|
||||
Selector: &nockchain.GetBalanceRequest_FirstName{
|
||||
FirstName: crypto.Tip5HashToBase58(firstName),
|
||||
},
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsuport version")
|
||||
}
|
||||
masterKeyScan, err := h.client.WalletGetBalance(scanReq)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -535,23 +531,30 @@ func (h *GprcHandler) CreateTx(ctx context.Context, req *nockchain.CreateTxReque
|
||||
notesV1Sort := make([]*nockchain.NockchainNoteV1, len(notesV1))
|
||||
copy(notesV1Sort, notesV1)
|
||||
|
||||
switch req.Version {
|
||||
case 0:
|
||||
slices.SortFunc(notesV0Sort, func(note1, note2 *nockchain.NockchainNoteV0) int {
|
||||
return cmp.Compare(note1.Asset, note2.Asset)
|
||||
return cmp.Compare(note2.Asset, note1.Asset)
|
||||
})
|
||||
// TODO: sort V1 notes
|
||||
case 1:
|
||||
slices.SortFunc(notesV1Sort, func(note1, note2 *nockchain.NockchainNoteV1) int {
|
||||
return cmp.Compare(note2.Assets, note1.Assets)
|
||||
})
|
||||
}
|
||||
|
||||
spends := []*nockchain.NockchainNamedSpend{}
|
||||
for _, note := range notesV0Sort {
|
||||
giftPortion := uint64(0)
|
||||
feePortion := uint64(0)
|
||||
if giftRemaining != 0 {
|
||||
giftPortion = min(giftRemaining, note.Asset)
|
||||
for i := 0; i < len(names); i++ {
|
||||
asset := uint64(0)
|
||||
switch req.Version {
|
||||
case 0:
|
||||
asset = notesV0Sort[i].Asset
|
||||
case 1:
|
||||
asset = notesV1Sort[i].Assets
|
||||
}
|
||||
giftPortion := min(giftRemaining, asset)
|
||||
|
||||
feeAvailable := note.Asset - giftPortion
|
||||
if feeRemaining != 0 {
|
||||
feePortion = min(feeRemaining, feeAvailable)
|
||||
}
|
||||
feeAvailable := asset - giftPortion
|
||||
feePortion := min(feeRemaining, feeAvailable)
|
||||
|
||||
if giftPortion == 0 && feePortion == 0 {
|
||||
continue
|
||||
@ -560,32 +563,38 @@ func (h *GprcHandler) CreateTx(ctx context.Context, req *nockchain.CreateTxReque
|
||||
giftRemaining = giftRemaining - giftPortion
|
||||
feeRemaining = feeRemaining - feePortion
|
||||
|
||||
refund := note.Asset - giftPortion - feePortion
|
||||
refund := asset - giftPortion - feePortion
|
||||
if refund == 0 && giftPortion == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
parentHash, err := HashNoteV0(note)
|
||||
var parentHash [5]uint64
|
||||
switch req.Version {
|
||||
case 0:
|
||||
parentHash, err = HashNoteV0(notesV0Sort[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.Version == 0 {
|
||||
case 1:
|
||||
parentHash = HashNoteV1(notesV1Sort[i])
|
||||
}
|
||||
lockRoot := HashLock(recipent)
|
||||
seeds := []*nockchain.NockchainSeed{}
|
||||
if giftPortion != 0 {
|
||||
wordCount += SeedWordsCount
|
||||
seeds := []*nockchain.NockchainSeedV0{
|
||||
{
|
||||
seeds = append(seeds, &nockchain.NockchainSeed{
|
||||
OutputSource: nil,
|
||||
LockRoot: crypto.Tip5HashToBase58(lockRoot),
|
||||
NoteData: recipent,
|
||||
Gift: giftPortion,
|
||||
ParentHash: crypto.Tip5HashToBase58(parentHash),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if refund != 0 {
|
||||
wordCount += SeedWordsCount
|
||||
lockRoot := HashLock(refundLock)
|
||||
seeds = append(seeds, &nockchain.NockchainSeedV0{
|
||||
seeds = append(seeds, &nockchain.NockchainSeed{
|
||||
OutputSource: nil,
|
||||
LockRoot: crypto.Tip5HashToBase58(lockRoot),
|
||||
NoteData: refundLock,
|
||||
@ -594,17 +603,10 @@ func (h *GprcHandler) CreateTx(ctx context.Context, req *nockchain.CreateTxReque
|
||||
})
|
||||
}
|
||||
|
||||
spend := nockchain.NockchainSpendV0{
|
||||
Signatures: nil,
|
||||
Seeds: seeds,
|
||||
Fee: feePortion,
|
||||
}
|
||||
|
||||
msg, err := HashMsg(&spend)
|
||||
msg, err := HashMsg(seeds, feePortion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Println("msg:", msg)
|
||||
|
||||
// sign
|
||||
chalT8, sigT8, err := ComputeSig(*masterKey, msg)
|
||||
@ -612,27 +614,73 @@ func (h *GprcHandler) CreateTx(ctx context.Context, req *nockchain.CreateTxReque
|
||||
return nil, err
|
||||
}
|
||||
|
||||
masterPkPoint, err := crypto.CheetaPointFromBytes(masterKey.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Println("master pk point:", masterPkPoint)
|
||||
spend.Signatures = []*nockchain.NockchainSignature{
|
||||
sigs := []*nockchain.NockchainSignature{
|
||||
{
|
||||
Pubkey: base58.Encode(masterKey.PublicKey),
|
||||
Chal: chalT8[:],
|
||||
Sig: sigT8[:],
|
||||
},
|
||||
}
|
||||
switch req.Version {
|
||||
case 0:
|
||||
spend := nockchain.NockchainSpendV0{
|
||||
Signatures: nil,
|
||||
Seeds: seeds,
|
||||
Fee: feePortion,
|
||||
}
|
||||
|
||||
spend.Signatures = sigs
|
||||
wordCount += SignatureWordsCount
|
||||
nameIdx := -1
|
||||
for j := 0; j < len(names); j++ {
|
||||
if nnames[j].Last == notesV0Sort[i].Name.Last {
|
||||
nameIdx = j
|
||||
break
|
||||
}
|
||||
}
|
||||
spends = append(spends, &nockchain.NockchainNamedSpend{
|
||||
Name: note.Name,
|
||||
Name: nnames[nameIdx],
|
||||
SpendKind: &nockchain.NockchainNamedSpend_Legacy{
|
||||
Legacy: &spend,
|
||||
},
|
||||
})
|
||||
case 1:
|
||||
spend := nockchain.NockchainSpendV1{
|
||||
Witness: nil,
|
||||
Seeds: seeds,
|
||||
Fee: feePortion,
|
||||
}
|
||||
|
||||
spend.Witness = []*nockchain.NockchainWitness{
|
||||
{
|
||||
Lmp: &nockchain.NockchainLockMerkleProof{
|
||||
SpendCondition: ownerLock,
|
||||
Axis: 1,
|
||||
MerkleRoot: crypto.Tip5HashToBase58(ownerHash),
|
||||
},
|
||||
Pkh: sigs,
|
||||
},
|
||||
}
|
||||
wordCount += WitnessWordsCount
|
||||
nameIdx := -1
|
||||
for j := 0; j < len(names); j++ {
|
||||
if nnames[j].Last == notesV1Sort[i].Name.Last {
|
||||
nameIdx = j
|
||||
break
|
||||
}
|
||||
}
|
||||
spends = append(spends, &nockchain.NockchainNamedSpend{
|
||||
Name: nnames[nameIdx],
|
||||
SpendKind: &nockchain.NockchainNamedSpend_Witness{
|
||||
Witness: &spend,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if giftRemaining != 0 || feeRemaining != 0 {
|
||||
return nil, fmt.Errorf("insufficient funds to pay fee and gift")
|
||||
}
|
||||
|
||||
if wordCount*BaseFee > int(req.Fee) {
|
||||
|
||||
@ -435,7 +435,7 @@ func TestScan(t *testing.T) {
|
||||
assert.NotEmpty(t, masterKey1Scan.Notes)
|
||||
}
|
||||
|
||||
func TestEncodeNoun(t *testing.T) {
|
||||
func TestEncodeDecodeNoun(t *testing.T) {
|
||||
lock1 := &nockchain.NockchainLock{
|
||||
KeysRequired: 1,
|
||||
Pubkeys: []string{"5wef35rKxbJDJRAtzGG1VwbMQK9jF3Wr5e6fyMsh2hxnCQZDZJV1YNQ"},
|
||||
@ -444,143 +444,22 @@ func TestEncodeNoun(t *testing.T) {
|
||||
lock1Encode := wallet.EncodeNoteData(lock1)
|
||||
assert.Equal(t, lock1Encode, []byte{89, 192, 131, 91, 67, 199, 5, 16, 32, 24, 199, 52, 39, 171, 121, 6, 15, 240, 167, 243, 69, 34, 254, 110, 4, 78, 3, 8, 44, 245, 128, 176, 69, 72, 150, 253, 6, 232, 167, 34, 133, 115, 154, 56, 106, 106, 192, 175, 176, 88, 89, 160, 208, 117, 55, 78, 5})
|
||||
|
||||
lock1Decode := wallet.DecodeNoteData(lock1Encode)
|
||||
assert.Equal(t, lock1Decode.KeysRequired, lock1.KeysRequired)
|
||||
assert.Equal(t, lock1Decode.Pubkeys, lock1.Pubkeys)
|
||||
|
||||
lock2 := lock1
|
||||
lock2.Pubkeys = []string{"7UXNF2HXzEaPUvLDVDgGJyriKqpd2974Kj7U2RnLuBPeRGa7ZezhGmK"}
|
||||
lock2Encode := wallet.EncodeNoteData(lock2)
|
||||
assert.Equal(t, lock2Encode, []byte{89, 192, 131, 91, 67, 199, 5, 248, 151, 186, 241, 213, 183, 156, 103, 181, 1, 254, 206, 33, 184, 3, 142, 3, 99, 101, 0, 1, 246, 168, 22, 252, 21, 155, 53, 205, 0, 2, 172, 67, 150, 149, 228, 139, 80, 206, 0, 1, 203, 54, 188, 141, 54, 21, 39, 193, 84})
|
||||
|
||||
lock2Decode := wallet.DecodeNoteData(lock2Encode)
|
||||
assert.Equal(t, lock2Decode.KeysRequired, lock2.KeysRequired)
|
||||
assert.Equal(t, lock2Decode.Pubkeys, lock2.Pubkeys)
|
||||
}
|
||||
|
||||
// // This test should be run with timeout 120s
|
||||
// func TestFullFlow(t *testing.T) {
|
||||
// mnemonic1 := "rail nurse smile angle uphold gun kitten spoon quick frozen trigger cable decorate episode blame tray off bag arena taxi approve breeze job letter"
|
||||
// masterKey1, err := crypto.MasterKeyFromSeed(mnemonic1)
|
||||
// assert.NoError(t, err)
|
||||
// fmt.Println(base58.Encode(masterKey1.PublicKey))
|
||||
// mnemonic2 := "brass vacuum stairs hurt brisk govern describe enforce fly exact rescue capable belt flavor lottery sauce easy frame orange legal injury border obey novel"
|
||||
// masterKey2, err := crypto.MasterKeyFromSeed(mnemonic2)
|
||||
// assert.NoError(t, err)
|
||||
|
||||
// inputName := "[4taoqkpysafnp64WBQyzHDKVrqkMeNrdAiVSbWdzZmj7yQYZgQtCq4W 9cjUFbdtaFHeXNWCAKjsTphBchHmCoUU6a1aDbJAFz9qHqeG8osh4wF]"
|
||||
|
||||
// nc, err := wallet.NewNockchainClient("nockchain-api.zorp.io:443")
|
||||
// assert.NoError(t, err)
|
||||
|
||||
// masterKeyScan, err := nc.WalletGetBalance(base58.Encode(masterKey1.PublicKey))
|
||||
// assert.NoError(t, err)
|
||||
|
||||
// var note *nockchain.NockchainNote
|
||||
// for _, balanceEntry := range masterKeyScan.Notes {
|
||||
// firstName := crypto.Tip5HashToBase58([5]uint64{
|
||||
// balanceEntry.Name.First.Belt_1.Value,
|
||||
// balanceEntry.Name.First.Belt_2.Value,
|
||||
// balanceEntry.Name.First.Belt_3.Value,
|
||||
// balanceEntry.Name.First.Belt_4.Value,
|
||||
// balanceEntry.Name.First.Belt_5.Value,
|
||||
// })
|
||||
// lastName := crypto.Tip5HashToBase58([5]uint64{
|
||||
// balanceEntry.Name.Last.Belt_1.Value,
|
||||
// balanceEntry.Name.Last.Belt_2.Value,
|
||||
// balanceEntry.Name.Last.Belt_3.Value,
|
||||
// balanceEntry.Name.Last.Belt_4.Value,
|
||||
// balanceEntry.Name.Last.Belt_5.Value,
|
||||
// })
|
||||
// nname := "[" + firstName + " " + lastName + "]"
|
||||
// if nname == inputName {
|
||||
// nnote := wallet.ParseBalanceEntry(balanceEntry)
|
||||
// note = &nnote
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// assert.NotNil(t, note)
|
||||
|
||||
// parentHash, err := wallet.HashNote(note)
|
||||
// assert.NoError(t, err)
|
||||
|
||||
// gift := uint64(100000)
|
||||
// seed1 := &nockchain.NockchainSeed{
|
||||
// OutputSource: nil,
|
||||
// Recipient: &nockchain.NockchainLock{
|
||||
// KeysRequired: 1,
|
||||
// Pubkeys: []string{base58.Encode(masterKey2.PublicKey)},
|
||||
// },
|
||||
// TimelockIntent: nil,
|
||||
// Gift: gift,
|
||||
// ParentHash: crypto.Tip5HashToBase58(parentHash),
|
||||
// }
|
||||
|
||||
// gift = note.Asset - gift - 100
|
||||
// seed2 := &nockchain.NockchainSeed{
|
||||
// OutputSource: nil,
|
||||
// Recipient: &nockchain.NockchainLock{
|
||||
// KeysRequired: 1,
|
||||
// Pubkeys: []string{base58.Encode(masterKey1.PublicKey)},
|
||||
// },
|
||||
// TimelockIntent: nil,
|
||||
// Gift: gift,
|
||||
// ParentHash: crypto.Tip5HashToBase58(parentHash),
|
||||
// }
|
||||
|
||||
// spend := nockchain.NockchainSpend{
|
||||
// Signatures: nil,
|
||||
// Seeds: []*nockchain.NockchainSeed{
|
||||
// seed1, seed2,
|
||||
// },
|
||||
// Fee: 100,
|
||||
// }
|
||||
|
||||
// msg, err := wallet.HashMsg(&spend)
|
||||
// assert.NoError(t, err)
|
||||
|
||||
// chalT8, sigT8, err := wallet.ComputeSig(*masterKey1, msg)
|
||||
// assert.NoError(t, err)
|
||||
|
||||
// spend.Signatures = []*nockchain.NockchainSignature{
|
||||
// {
|
||||
// Pubkey: base58.Encode(masterKey1.PublicKey),
|
||||
// Chal: chalT8[:],
|
||||
// Sig: sigT8[:],
|
||||
// },
|
||||
// }
|
||||
|
||||
// input := nockchain.NockchainInput{
|
||||
// Name: &nockchain.NockchainName{
|
||||
// First: "4taoqkpysafnp64WBQyzHDKVrqkMeNrdAiVSbWdzZmj7yQYZgQtCq4W",
|
||||
// Last: "9cjUFbdtaFHeXNWCAKjsTphBchHmCoUU6a1aDbJAFz9qHqeG8osh4wF",
|
||||
// },
|
||||
// Note: note,
|
||||
// Spend: &spend,
|
||||
// }
|
||||
|
||||
// id, err := wallet.ComputeTxId([]*nockchain.NockchainInput{&input}, &nockchain.TimelockRange{
|
||||
// Min: nil,
|
||||
// Max: nil,
|
||||
// }, 100)
|
||||
// assert.NoError(t, err)
|
||||
|
||||
// rawTx := nockchain.RawTx{
|
||||
// TxId: crypto.Tip5HashToBase58(id),
|
||||
// Inputs: []*nockchain.NockchainInput{&input},
|
||||
// TimelockRange: &nockchain.TimelockRange{
|
||||
// Min: nil,
|
||||
// Max: nil,
|
||||
// },
|
||||
// TotalFees: 100,
|
||||
// }
|
||||
// resp, err := nc.WalletSendTransaction(&rawTx)
|
||||
// assert.NoError(t, err)
|
||||
// assert.Equal(t, resp.Result, &nockchain.WalletSendTransactionResponse_Ack{
|
||||
// Ack: &nockchain.Acknowledged{},
|
||||
// })
|
||||
|
||||
// txAcceptedResp, err := nc.TxAccepted(rawTx.TxId)
|
||||
// assert.NoError(t, err)
|
||||
// assert.Equal(t, txAcceptedResp.Result, &nockchain.TransactionAcceptedResponse_Accepted{
|
||||
// Accepted: true,
|
||||
// })
|
||||
// }
|
||||
|
||||
// This test should be run with timeout 300s
|
||||
func TestCreateTx(t *testing.T) {
|
||||
func TestCreateTxV0(t *testing.T) {
|
||||
seed1 := "rail nurse smile angle uphold gun kitten spoon quick frozen trigger cable decorate episode blame tray off bag arena taxi approve breeze job letter"
|
||||
masterKey1, err := crypto.MasterKeyFromSeed(seed1)
|
||||
assert.NoError(t, err)
|
||||
@ -626,3 +505,34 @@ func TestCreateTx(t *testing.T) {
|
||||
// the result is taken from create-tx scripts
|
||||
assert.Equal(t, res.RawTx.TxId, "6oDgTWnk6sL98yK49hcQTRAfCdFfgKh58U6TDTKmGPirhoxkMii2D6E")
|
||||
}
|
||||
|
||||
func TestCreateTxV1(t *testing.T) {
|
||||
seed := "pledge vessel toilet sunny hockey skirt spend wire disorder attitude crumble lecture problem bundle bone rather address over suit ancient primary gospel silent repair"
|
||||
_, err := crypto.MasterKeyFromSeed(seed)
|
||||
assert.NoError(t, err)
|
||||
|
||||
nc, err := wallet.NewNockchainClient("nockchain-api.zorp.io:443")
|
||||
assert.NoError(t, err)
|
||||
handler := wallet.NewGprcHandler(*nc)
|
||||
|
||||
inputs := "[9McQZWZzqFCLwsF37gUHLHt3cxWVbLA64SabN3AMMSgNuSM2b9SmMsj 88uZqY63kneffJnVAEYpb67W96sk3xsdFYTjzj8DSBiigL9AZd9pHsC],[9McQZWZzqFCLwsF37gUHLHt3cxWVbLA64SabN3AMMSgNuSM2b9SmMsj 2JLcp5oXBTtgTCKN4na9Dnk2YuHJCXuDAkk5qT8n9iP1d4iz1c3Amfo]"
|
||||
|
||||
recipients := fmt.Sprintf("%s:747336", "D6NUb9HC4ursvZzYdMAtWAMSyyJWwtdqnsyRXxsADsyqQwh5dcDsTRm")
|
||||
fee := 4456448
|
||||
|
||||
req := &nockchain.CreateTxRequest{
|
||||
Names: inputs,
|
||||
Recipients: recipients,
|
||||
Fee: uint64(fee),
|
||||
IsMasterKey: true,
|
||||
Seed: seed,
|
||||
Index: 0,
|
||||
Hardened: false,
|
||||
Version: 1,
|
||||
}
|
||||
|
||||
resp, err := handler.CreateTx(context.Background(), req)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, resp.RawTx.TxId, "9DfaTJgtsGU8Fs2mAPhGpiMMw5RcRXjEVfnmFcTTxoSFMLWpv2Ae4eG")
|
||||
}
|
||||
|
||||
138
wallet/types.go
138
wallet/types.go
@ -1,14 +1,28 @@
|
||||
package wallet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil/base58"
|
||||
"github.com/phamminh0811/private-grpc/crypto"
|
||||
"github.com/phamminh0811/private-grpc/nockchain"
|
||||
)
|
||||
|
||||
func ParseBalanceEntry(entry *nockchain.BalanceEntry) nockchain.NockchainNote {
|
||||
name := &nockchain.NockchainName{
|
||||
First: crypto.Tip5HashToBase58([5]uint64{
|
||||
entry.Name.First.Belt_1.Value,
|
||||
entry.Name.First.Belt_2.Value,
|
||||
entry.Name.First.Belt_3.Value,
|
||||
entry.Name.First.Belt_4.Value,
|
||||
entry.Name.First.Belt_5.Value,
|
||||
}),
|
||||
Last: crypto.Tip5HashToBase58([5]uint64{
|
||||
entry.Name.Last.Belt_1.Value,
|
||||
entry.Name.Last.Belt_2.Value,
|
||||
entry.Name.Last.Belt_3.Value,
|
||||
entry.Name.Last.Belt_4.Value,
|
||||
entry.Name.Last.Belt_5.Value,
|
||||
}),
|
||||
}
|
||||
switch entry.Note.NoteVersion.(type) {
|
||||
case *nockchain.Note_Legacy:
|
||||
note := entry.Note.GetLegacy()
|
||||
@ -50,22 +64,7 @@ func ParseBalanceEntry(entry *nockchain.BalanceEntry) nockchain.NockchainNote {
|
||||
V0: &nockchain.NockchainNoteV0{
|
||||
Version: version,
|
||||
OriginPage: note.OriginPage.Value,
|
||||
Name: &nockchain.NockchainName{
|
||||
First: crypto.Tip5HashToBase58([5]uint64{
|
||||
entry.Name.First.Belt_1.Value,
|
||||
entry.Name.First.Belt_2.Value,
|
||||
entry.Name.First.Belt_3.Value,
|
||||
entry.Name.First.Belt_4.Value,
|
||||
entry.Name.First.Belt_5.Value,
|
||||
}),
|
||||
Last: crypto.Tip5HashToBase58([5]uint64{
|
||||
entry.Name.Last.Belt_1.Value,
|
||||
entry.Name.Last.Belt_2.Value,
|
||||
entry.Name.Last.Belt_3.Value,
|
||||
entry.Name.Last.Belt_4.Value,
|
||||
entry.Name.Last.Belt_5.Value,
|
||||
}),
|
||||
},
|
||||
Name: name,
|
||||
Lock: &nockchain.NockchainLock{
|
||||
KeysRequired: uint64(note.Lock.KeysRequired),
|
||||
Pubkeys: pubkeys,
|
||||
@ -79,11 +78,22 @@ func ParseBalanceEntry(entry *nockchain.BalanceEntry) nockchain.NockchainNote {
|
||||
},
|
||||
}
|
||||
case *nockchain.Note_V1:
|
||||
fmt.Println("go here???")
|
||||
// Handle V1 notes if needed
|
||||
note := entry.Note.GetV1()
|
||||
version := nockchain.Version(note.Version.Value)
|
||||
if len(note.NoteData.Entries) != 1 || note.NoteData.Entries[0].Key != "lock" {
|
||||
panic("invalid note data")
|
||||
}
|
||||
lock := DecodeNoteData(note.NoteData.Entries[0].Blob)
|
||||
|
||||
return nockchain.NockchainNote{
|
||||
Note: &nockchain.NockchainNote_V1{
|
||||
V1: &nockchain.NockchainNoteV1{},
|
||||
V1: &nockchain.NockchainNoteV1{
|
||||
Version: version,
|
||||
OriginPage: note.OriginPage.Value,
|
||||
Name: name,
|
||||
NoteData: lock,
|
||||
Assets: note.Assets.Value,
|
||||
},
|
||||
},
|
||||
}
|
||||
default:
|
||||
@ -134,7 +144,91 @@ func ConvertNamedSpend(spend *nockchain.NockchainNamedSpend) (*nockchain.SpendEn
|
||||
},
|
||||
}
|
||||
case *nockchain.NockchainNamedSpend_Witness:
|
||||
// TODO: handle v1
|
||||
witnessSpend := spend.GetWitness()
|
||||
seeds := []*nockchain.Seed{}
|
||||
for _, seed := range witnessSpend.Seeds {
|
||||
seeds = append(seeds, &nockchain.Seed{
|
||||
OutputSource: &nockchain.Source{
|
||||
Hash: ParseHash(seed.OutputSource.Source),
|
||||
Coinbase: seed.OutputSource.IsCoinbase,
|
||||
},
|
||||
LockRoot: ParseHash(seed.LockRoot),
|
||||
NoteData: &nockchain.NoteData{
|
||||
Entries: []*nockchain.NoteDataEntry{
|
||||
{
|
||||
Key: "lock",
|
||||
Blob: EncodeNoteData(seed.NoteData),
|
||||
},
|
||||
},
|
||||
},
|
||||
Gift: &nockchain.Nicks{
|
||||
Value: seed.Gift,
|
||||
},
|
||||
ParentHash: ParseHash(seed.ParentHash),
|
||||
})
|
||||
}
|
||||
|
||||
witness := witnessSpend.Witness[0]
|
||||
lockHashes := []*nockchain.Hash{}
|
||||
for i := 0; i < len(witness.Lmp.SpendCondition.Pubkeys); i++ {
|
||||
lockHashes = append(lockHashes, ParseHash(witness.Lmp.SpendCondition.Pubkeys[i]))
|
||||
}
|
||||
|
||||
pkhSigs := []*nockchain.PkhSignatureEntry{}
|
||||
for _, pkh := range witness.Pkh {
|
||||
pk, err := crypto.CheetaPointFromBytes(base58.Decode(pkh.Pubkey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
schnorrPk, err := ParseSchnorrPubkey(pkh.Pubkey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pkHash := HashPubkey(pk)
|
||||
pkhSigs = append(pkhSigs, &nockchain.PkhSignatureEntry{
|
||||
Hash: ParseHash(crypto.Tip5HashToBase58(pkHash)),
|
||||
Pubkey: schnorrPk,
|
||||
Signature: &nockchain.SchnorrSignature{
|
||||
Chal: ParseEightBelt(pkh.Chal),
|
||||
Sig: ParseEightBelt(pkh.Sig),
|
||||
},
|
||||
})
|
||||
}
|
||||
convertedSpend = &nockchain.Spend{
|
||||
SpendKind: &nockchain.Spend_Witness{
|
||||
Witness: &nockchain.WitnessSpend{
|
||||
Witness: &nockchain.Witness{
|
||||
LockMerkleProof: &nockchain.LockMerkleProof{
|
||||
SpendCondition: &nockchain.SpendCondition{
|
||||
Primitives: []*nockchain.LockPrimitive{
|
||||
{
|
||||
Primitive: &nockchain.LockPrimitive_Pkh{
|
||||
Pkh: &nockchain.PkhLock{
|
||||
M: witness.Lmp.SpendCondition.KeysRequired,
|
||||
Hashes: lockHashes,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Axis: witness.Lmp.Axis,
|
||||
Proof: &nockchain.MerkleProof{
|
||||
Root: ParseHash(witness.Lmp.MerkleRoot),
|
||||
Path: []*nockchain.Hash{},
|
||||
},
|
||||
},
|
||||
PkhSignature: &nockchain.PkhSignature{
|
||||
Entries: pkhSigs,
|
||||
},
|
||||
},
|
||||
Seeds: seeds,
|
||||
Fee: &nockchain.Nicks{
|
||||
Value: witnessSpend.Fee,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
// Conversion logic here
|
||||
return &nockchain.SpendEntry{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user