forked from FactomProject/factomd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
newCoinbaseAddress.go
150 lines (127 loc) · 4.34 KB
/
newCoinbaseAddress.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright 2017 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.
package identityEntries
import (
"fmt"
"reflect"
"github.com/FactomProject/factomd/common/entryBlock"
"github.com/FactomProject/factomd/common/interfaces"
"github.com/FactomProject/factomd/common/primitives"
)
// https://github.com/FactomProject/FactomDocs/blob/master/Identity.md#coinbase-address
type NewCoinbaseAddressStruct struct {
//The message is a Factom Entry with several extIDs holding the various parts.
//[0 (version)] [Coinbase Address] [identity ChainID] [new factoid address] [timestamp] [identity key preimage] [signature of version through timestamp]
//The first part is a version binary string 0.
Version byte
//The second is the ASCII string "Coinbase Address".
FunctionName []byte //"Server Efficiency"
//The third is the root identity ChainID.
RootIdentityChainID interfaces.IHash
//Forth is the new coinbase address
CoinbaseAddress interfaces.IHash
//5th is the timestamp with an 8 byte epoch time.
Timestamp []byte
//6th is the identity key preimage.
PreimageIdentityKey []byte
//7th is the signature of the serialized version through timestamp.
Signature []byte
}
func DecodeNewNewCoinbaseAddressStructFromExtIDs(extIDs [][]byte) (*NewCoinbaseAddressStruct, error) {
nbsk := new(NewCoinbaseAddressStruct)
err := nbsk.DecodeFromExtIDs(extIDs)
if err != nil {
return nil, err
}
return nbsk, nil
}
func (ncas *NewCoinbaseAddressStruct) SetFunctionName() {
ncas.FunctionName = []byte("Coinbase Address")
}
func (ncas *NewCoinbaseAddressStruct) MarshalForSig() []byte {
answer := []byte{}
answer = append(answer, ncas.Version)
answer = append(answer, ncas.FunctionName...)
answer = append(answer, ncas.RootIdentityChainID.Bytes()...)
answer = append(answer, ncas.CoinbaseAddress.Bytes()...)
answer = append(answer, ncas.Timestamp...)
return answer
}
func (ncas *NewCoinbaseAddressStruct) VerifySignature(key1 interfaces.IHash) error {
bin := ncas.MarshalForSig()
pk := new(primitives.PublicKey)
err := pk.UnmarshalBinary(ncas.PreimageIdentityKey[1:])
if err != nil {
return err
}
var sig [64]byte
copy(sig[:], ncas.Signature)
ok := pk.Verify(bin, &sig)
if ok == false {
return fmt.Errorf("Invalid signature")
}
if key1 == nil {
return nil
}
hashedKey := primitives.Shad(ncas.PreimageIdentityKey)
if hashedKey.IsSameAs(key1) == false {
return fmt.Errorf("PreimageIdentityKey does not equal Key1 - %v vs %v", hashedKey, key1)
}
return nil
}
func (ncas *NewCoinbaseAddressStruct) DecodeFromExtIDs(extIDs [][]byte) error {
if len(extIDs) != 7 {
return fmt.Errorf("Wrong number of ExtIDs - expected 7, got %v", len(extIDs))
}
if CheckExternalIDsLength(extIDs, []int{1, 16, 32, 32, 8, 33, 64}) == false {
return fmt.Errorf("Wrong lengths of ExtIDs")
}
ncas.Version = extIDs[0][0]
if ncas.Version != 0 {
return fmt.Errorf("Wrong Version - expected 0, got %v", ncas.Version)
}
ncas.FunctionName = extIDs[1]
if string(ncas.FunctionName) != "Coinbase Address" {
return fmt.Errorf("Invalid FunctionName - expected 'Coinbase Address', got '%s'", ncas.FunctionName)
}
h, err := primitives.NewShaHash(extIDs[2])
if err != nil {
return err
}
ncas.RootIdentityChainID = h
h, err = primitives.NewShaHash(extIDs[3])
if err != nil {
return err
}
ncas.CoinbaseAddress = h
ncas.Timestamp = extIDs[4]
ncas.PreimageIdentityKey = extIDs[5]
ncas.Signature = extIDs[6]
err = ncas.VerifySignature(nil)
if err != nil {
return err
}
return nil
}
func (ncas *NewCoinbaseAddressStruct) ToExternalIDs() [][]byte {
extIDs := [][]byte{}
extIDs = append(extIDs, []byte{ncas.Version})
extIDs = append(extIDs, ncas.FunctionName)
extIDs = append(extIDs, ncas.RootIdentityChainID.Bytes())
extIDs = append(extIDs, ncas.CoinbaseAddress.Bytes())
extIDs = append(extIDs, ncas.Timestamp)
extIDs = append(extIDs, ncas.PreimageIdentityKey)
extIDs = append(extIDs, ncas.Signature)
return extIDs
}
func (ncas *NewCoinbaseAddressStruct) GetChainID() (rval interfaces.IHash) {
defer func() {
if rval != nil && reflect.ValueOf(rval).IsNil() {
rval = nil // convert an interface that is nil to a nil interface
primitives.LogNilHashBug("NewCoinbaseAddressStruct.GetChainID() saw an interface that was nil")
}
}()
extIDs := ncas.ToExternalIDs()
return entryBlock.ExternalIDsToChainID(extIDs)
}