WIP
This commit is contained in:
parent
91b2ed32a5
commit
e4edf2338e
10
key.go
10
key.go
|
@ -2,6 +2,7 @@ package moneroutil
|
|||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"io"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -55,3 +56,12 @@ func NewKeyPair() (privKey *Key, pubKey *Key) {
|
|||
pubKey = privKey.PubKey()
|
||||
return
|
||||
}
|
||||
|
||||
func ParseKey(buf io.Reader) (result Key, err error) {
|
||||
key := make([]byte, KeyLength)
|
||||
if _, err = buf.Read(key); err != nil {
|
||||
return
|
||||
}
|
||||
copy(result[:], key)
|
||||
return
|
||||
}
|
||||
|
|
50
ringct.go
50
ringct.go
|
@ -11,20 +11,12 @@ const (
|
|||
RCTTypeSimple
|
||||
)
|
||||
|
||||
// V = Vector, M = Matrix
|
||||
type KeyV []Key
|
||||
type KeyM []KeyV
|
||||
|
||||
// Confidential Transaction Keys
|
||||
type CtKey struct {
|
||||
destination Key
|
||||
mask Key
|
||||
}
|
||||
|
||||
// V = Vector, M = Matrix
|
||||
type CtKeyV []CtKey
|
||||
type CtKeyM []CtKeyV
|
||||
|
||||
// Pedersen Commitment is generated from this struct
|
||||
// C = aG + bH where a = mask and b = amount
|
||||
// senderPk is the one-time public key for ECDH exchange
|
||||
|
@ -44,10 +36,10 @@ type BoroSig struct {
|
|||
}
|
||||
|
||||
// MLSAG (Multilayered Linkable Spontaneous Anonymous Group) Signature
|
||||
type MgSig struct {
|
||||
ss KeyM
|
||||
type MlsagSig struct {
|
||||
ss [][]Key
|
||||
cc Key
|
||||
ii KeyV
|
||||
ii []Key
|
||||
}
|
||||
|
||||
// Range Signature
|
||||
|
@ -61,16 +53,16 @@ type RangeSig struct {
|
|||
type RctSigBase struct {
|
||||
sigType uint8
|
||||
message Key
|
||||
mixRing CtKeyM
|
||||
pseudoOuts KeyV
|
||||
mixRing [][]CtKey
|
||||
pseudoOuts []Key
|
||||
ecdhInfo []ecdhTuple
|
||||
outPk CtKeyV
|
||||
outPk []CtKey
|
||||
txFee uint64
|
||||
}
|
||||
|
||||
type RctSigPrunable struct {
|
||||
rangeSigs []RangeSig
|
||||
mgSigs []MgSig
|
||||
mlsagSigs []MlsagSig
|
||||
}
|
||||
|
||||
type RctSig struct {
|
||||
|
@ -164,7 +156,7 @@ func (r *RangeSig) Serialize() (result []byte) {
|
|||
return
|
||||
}
|
||||
|
||||
func (m *MgSig) Serialize() (result []byte) {
|
||||
func (m *MlsagSig) Serialize() (result []byte) {
|
||||
for i := 0; i < len(m.ss); i++ {
|
||||
for j := 0; j < len(m.ss[i]); j++ {
|
||||
result = append(result, m.ss[i][j][:]...)
|
||||
|
@ -208,8 +200,8 @@ func (r *RctSig) SerializePrunable() (result []byte) {
|
|||
for _, rangeSig := range r.rangeSigs {
|
||||
result = append(result, rangeSig.Serialize()...)
|
||||
}
|
||||
for _, mgSig := range r.mgSigs {
|
||||
result = append(result, mgSig.Serialize()...)
|
||||
for _, mlsagSig := range r.mlsagSigs {
|
||||
result = append(result, mlsagSig.Serialize()...)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -271,13 +263,13 @@ func (r *RctSig) VerifyRctSimple() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func ParseKey(buf io.Reader) (result Key, err error) {
|
||||
key := make([]byte, KeyLength)
|
||||
if _, err = buf.Read(key); err != nil {
|
||||
return
|
||||
func (r *RctSig) VerifyRctFull() bool {
|
||||
for i, ctKey := range r.outPk {
|
||||
if !verRange(&ctKey.mask, r.rangeSigs[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
copy(result[:], key)
|
||||
return
|
||||
return true
|
||||
}
|
||||
|
||||
func ParseCtKey(buf io.Reader) (result CtKey, err error) {
|
||||
|
@ -373,18 +365,18 @@ func ParseRingCtSignature(buf io.Reader, nInputs, nOutputs, nMixin int) (result
|
|||
return
|
||||
}
|
||||
}
|
||||
r.mgSigs = make([]MgSig, nMg)
|
||||
r.mlsagSigs = make([]MlsagSig, nMg)
|
||||
for i := 0; i < nMg; i++ {
|
||||
r.mgSigs[i].ss = make([]KeyV, nMixin+1)
|
||||
r.mlsagSigs[i].ss = make([][]Key, nMixin+1)
|
||||
for j := 0; j < nMixin+1; j++ {
|
||||
r.mgSigs[i].ss[j] = make([]Key, nSS)
|
||||
r.mlsagSigs[i].ss[j] = make([]Key, nSS)
|
||||
for k := 0; k < nSS; k++ {
|
||||
if r.mgSigs[i].ss[j][k], err = ParseKey(buf); err != nil {
|
||||
if r.mlsagSigs[i].ss[j][k], err = ParseKey(buf); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if r.mgSigs[i].cc, err = ParseKey(buf); err != nil {
|
||||
if r.mlsagSigs[i].cc, err = ParseKey(buf); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
58
ringct_test.go
Normal file
58
ringct_test.go
Normal file
File diff suppressed because one or more lines are too long
|
@ -13,15 +13,6 @@ const (
|
|||
|
||||
var UnimplementedError = fmt.Errorf("Unimplemented")
|
||||
|
||||
type txOutToKey struct {
|
||||
key Key
|
||||
}
|
||||
|
||||
type TxOutTargetSerializer interface {
|
||||
TargetSerialize() []byte
|
||||
String() string
|
||||
}
|
||||
|
||||
type txInGen struct {
|
||||
height uint64
|
||||
}
|
||||
|
@ -39,7 +30,7 @@ type TxInSerializer interface {
|
|||
|
||||
type TxOut struct {
|
||||
amount uint64
|
||||
target TxOutTargetSerializer
|
||||
key Key
|
||||
}
|
||||
|
||||
type TransactionPrefix struct {
|
||||
|
@ -54,6 +45,7 @@ type Transaction struct {
|
|||
TransactionPrefix
|
||||
signatures []RingSignature
|
||||
rctSignature *RctSig
|
||||
expanded bool
|
||||
}
|
||||
|
||||
func (h *Hash) Serialize() (result []byte) {
|
||||
|
@ -66,12 +58,13 @@ func (p *Key) Serialize() (result []byte) {
|
|||
return
|
||||
}
|
||||
|
||||
func (t *txOutToKey) TargetSerialize() (result []byte) {
|
||||
result = append([]byte{txOutToKeyMarker}, t.key.Serialize()...)
|
||||
func (t *TxOut) Serialize() (result []byte) {
|
||||
result = append(Uint64ToBytes(t.amount), txOutToKeyMarker)
|
||||
result = append(result, t.key[:]...)
|
||||
return
|
||||
}
|
||||
|
||||
func (t *txOutToKey) String() (result string) {
|
||||
func (t *TxOut) String() (result string) {
|
||||
result = fmt.Sprintf("key: %x", t.key)
|
||||
return
|
||||
}
|
||||
|
@ -99,11 +92,6 @@ func (t *txInToKey) MixinLen() int {
|
|||
return len(t.keyOffsets)
|
||||
}
|
||||
|
||||
func (t *TxOut) Serialize() (result []byte) {
|
||||
result = append(Uint64ToBytes(t.amount), t.target.TargetSerialize()...)
|
||||
return
|
||||
}
|
||||
|
||||
func (t *TransactionPrefix) SerializePrefix() (result []byte) {
|
||||
result = append(Uint64ToBytes(uint64(t.version)), Uint64ToBytes(t.unlockTime)...)
|
||||
result = append(result, Uint64ToBytes(uint64(len(t.vin)))...)
|
||||
|
@ -153,6 +141,49 @@ func (t *Transaction) SerializeBase() (result []byte) {
|
|||
return
|
||||
}
|
||||
|
||||
// ExpandTransaction does nothing for version 1 transactions, but for version 2
|
||||
// derives all the implied elements of the ring signature
|
||||
func (t *Transaction) ExpandTransaction(outputKeys [][]CtKey) {
|
||||
if t.version == 1 {
|
||||
return
|
||||
}
|
||||
r := t.rctSignature
|
||||
if r.sigType == RCTTypeNull {
|
||||
return
|
||||
}
|
||||
|
||||
// fill in the outPk property of the ring signature
|
||||
for i, ctKey := range r.outPk {
|
||||
ctKey.destination = t.vout[i].key
|
||||
}
|
||||
|
||||
r.message = Key(t.PrefixHash())
|
||||
if r.sigType == RCTTypeFull {
|
||||
r.mixRing = make([][]CtKey, len(outputKeys[0]))
|
||||
for i := 0; i < len(outputKeys); i++ {
|
||||
r.mixRing[i] = make([]CtKey, len(outputKeys))
|
||||
for j := 0; j < len(outputKeys[0]); j++ {
|
||||
r.mixRing[j][i] = outputKeys[i][j]
|
||||
}
|
||||
}
|
||||
r.mlsagSigs = make([]MlsagSig, 1)
|
||||
r.mlsagSigs[0].ii = make([]Key, len(t.vin))
|
||||
for i, txIn := range t.vin {
|
||||
txInWithKey, _ := txIn.(*txInToKey)
|
||||
r.mlsagSigs[0].ii[i] = txInWithKey.keyImage
|
||||
}
|
||||
} else if r.sigType == RCTTypeSimple {
|
||||
r.mixRing = outputKeys
|
||||
r.mlsagSigs = make([]MlsagSig, len(t.vin))
|
||||
for i, txIn := range t.vin {
|
||||
txInWithKey, _ := txIn.(*txInToKey)
|
||||
r.mlsagSigs[i].ii = make([]Key, 1)
|
||||
r.mlsagSigs[i].ii[0] = txInWithKey.keyImage
|
||||
}
|
||||
}
|
||||
t.expanded = true
|
||||
}
|
||||
|
||||
func (t *Transaction) GetHash() (result Hash) {
|
||||
if t.version == 1 {
|
||||
result = Keccak256(t.Serialize())
|
||||
|
@ -228,22 +259,6 @@ func ParseTxIn(buf io.Reader) (txIn TxInSerializer, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func ParseTxOutToKey(buf io.Reader) (txOutTarget *txOutToKey, err error) {
|
||||
t := new(txOutToKey)
|
||||
pubKey := make([]byte, KeyLength)
|
||||
n, err := buf.Read(pubKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if n != KeyLength {
|
||||
err = fmt.Errorf("Buffer not long enough for public key")
|
||||
return
|
||||
}
|
||||
copy(t.key[:], pubKey)
|
||||
txOutTarget = t
|
||||
return
|
||||
}
|
||||
|
||||
func ParseTxOut(buf io.Reader) (txOut *TxOut, err error) {
|
||||
t := new(TxOut)
|
||||
t.amount, err = ReadVarInt(buf)
|
||||
|
@ -261,7 +276,7 @@ func ParseTxOut(buf io.Reader) (txOut *TxOut, err error) {
|
|||
}
|
||||
switch {
|
||||
case marker[0] == txOutToKeyMarker:
|
||||
t.target, err = ParseTxOutToKey(buf)
|
||||
t.key, err = ParseKey(buf)
|
||||
default:
|
||||
err = fmt.Errorf("Bad Marker")
|
||||
return
|
||||
|
|
File diff suppressed because one or more lines are too long
Reference in a new issue