get serialization to work with sigs

This commit is contained in:
Jimmy Song 2017-05-03 12:31:17 -07:00
parent a7b35770f0
commit c1c77a72c8
2 changed files with 93 additions and 8 deletions

View file

@ -69,6 +69,7 @@ type txInToKey struct {
type TxInSerializer interface {
TxInSerialize() []byte
MixinLen() int
}
type TxOut struct {
@ -86,10 +87,7 @@ type TransactionPrefix struct {
type Transaction struct {
TransactionPrefix
signatures []Signature
ringSignatures []RingSignature
hash []byte
blobSize uint32
signatures [][]*Signature
}
func (h *Hash) Serialize() (result []byte) {
@ -151,6 +149,10 @@ func (t *txInGen) TxInSerialize() (result []byte) {
return
}
func (t *txInGen) MixinLen() int {
return 0
}
func (t *txInToScript) TxInSerialize() (result []byte) {
result = append([]byte{txInToScriptMarker}, t.prev...)
result = append(result, Uint64ToBytes(t.prevOut)...)
@ -158,6 +160,10 @@ func (t *txInToScript) TxInSerialize() (result []byte) {
return
}
func (t *txInToScript) MixinLen() int {
return 0
}
func (t *txInToScriptHash) TxInSerialize() (result []byte) {
result = append([]byte{txInToScriptHashMarker}, t.prev.Serialize()...)
result = append(result, Uint64ToBytes(t.prevOut)...)
@ -166,6 +172,10 @@ func (t *txInToScriptHash) TxInSerialize() (result []byte) {
return
}
func (t *txInToScriptHash) MixinLen() int {
return 0
}
func (t *txInToKey) TxInSerialize() (result []byte) {
result = append([]byte{txInToKeyMarker}, Uint64ToBytes(t.amount)...)
result = append(result, Uint64ToBytes(uint64(len(t.keyOffsets)))...)
@ -176,12 +186,16 @@ func (t *txInToKey) TxInSerialize() (result []byte) {
return
}
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) Serialize() (result []byte) {
func (t *TransactionPrefix) SerializePrefix() (result []byte) {
result = append(Uint64ToBytes(uint64(t.version)), Uint64ToBytes(t.unlockTime)...)
result = append(result, Uint64ToBytes(uint64(len(t.vin)))...)
for _, txIn := range t.vin {
@ -196,6 +210,16 @@ func (t *TransactionPrefix) Serialize() (result []byte) {
return
}
func (t *Transaction) Serialize() (result []byte) {
result = t.SerializePrefix()
for i := 0; i < len(t.signatures); i++ {
for j := 0; j < len(t.signatures[i]); j++ {
result = append(result, t.signatures[i][j].Serialize()...)
}
}
return
}
func ParseTxInGen(buf *bytes.Buffer) (txIn *txInGen, err error) {
t := new(txInGen)
t.height, err = ReadVarInt(buf)
@ -325,8 +349,42 @@ func ParseExtra(buf *bytes.Buffer) (extra []byte, err error) {
return
}
func ParseTransaction(buf *bytes.Buffer) (transaction *TransactionPrefix, err error) {
t := new(TransactionPrefix)
func ParseSignature(buf *bytes.Buffer) (signature *Signature, err error) {
s := new(Signature)
c := buf.Next(PubKeyLength)
if len(c) != PubKeyLength {
err = errors.New("Not enough bytes for signature c")
return
}
copy(s.c[:], c)
r := buf.Next(PubKeyLength)
if len(r) != PubKeyLength {
err = errors.New("Not enough bytes for signature r")
return
}
copy(s.r[:], r)
signature = s
return
}
func ParseSignatures(mixinLengths []int, buf *bytes.Buffer) (signatures [][]*Signature, err error) {
// mixinLengths is the number of mixins at each input position
sigs := make([][]*Signature, len(mixinLengths), len(mixinLengths))
for i, nMixin := range mixinLengths {
sigs[i] = make([]*Signature, nMixin, nMixin)
for j := 0; j < nMixin; j++ {
sigs[i][j], err = ParseSignature(buf)
if err != nil {
return
}
}
}
signatures = sigs
return
}
func ParseTransaction(buf *bytes.Buffer) (transaction *Transaction, err error) {
t := new(Transaction)
version, err := ReadVarInt(buf)
if err != nil {
return
@ -340,12 +398,17 @@ func ParseTransaction(buf *bytes.Buffer) (transaction *TransactionPrefix, err er
if err != nil {
return
}
var mixinLengths []int
t.vin = make([]TxInSerializer, int(numInputs), int(numInputs))
for i := 0; i < int(numInputs); i++ {
t.vin[i], err = ParseTxIn(buf)
if err != nil {
return
}
mixinLen := t.vin[i].MixinLen()
if mixinLen > 0 {
mixinLengths = append(mixinLengths, mixinLen)
}
}
numOutputs, err := ReadVarInt(buf)
if err != nil {
@ -362,6 +425,14 @@ func ParseTransaction(buf *bytes.Buffer) (transaction *TransactionPrefix, err er
if err != nil {
return
}
t.signatures, err = ParseSignatures(mixinLengths, buf)
if err != nil {
return
}
if buf.Len() != 0 {
err = errors.New("Buffer has extra data")
return
}
transaction = t
return
}

View file

@ -157,6 +157,7 @@ func TestTxInToKeyTransaction(t *testing.T) {
outputSum uint64
inputKeyImages []string
outputs []string
mixinLength int
}{
{
name: "50 inputs from block 58272",
@ -225,6 +226,7 @@ func TestTxInToKeyTransaction(t *testing.T) {
"02bfae014409db5bbb21cfe04224b42a6476697df719ecc8b0d8ac65245c05482a",
"022898f95d657d0fb76ebf551bea861d63657d71d53887df7f2aaa455c46488aaa",
},
mixinLength: 11,
},
}
for _, test := range tests {
@ -285,8 +287,20 @@ func TestTxInToKeyTransaction(t *testing.T) {
t.Errorf("%s: output %d: want %x, got %x", test.name, i, wantOut, gotOut)
}
}
wantLen = len(test.inputKeyImages)
gotLen = len(transaction.signatures)
if wantLen != gotLen {
t.Errorf("%s: signature len: want %d, got %d", test.name, wantLen, gotLen)
}
for i, mixins := range transaction.signatures {
wantLen = test.mixinLength
gotLen = len(mixins)
if wantLen != gotLen {
t.Errorf("%s: mixin len for %d: want %d, got %d", test.name, i, wantLen, gotLen)
}
}
gotSerialized := transaction.Serialize()
wantSerialized := serializedTx[:len(gotSerialized)]
wantSerialized := serializedTx
if bytes.Compare(wantSerialized, gotSerialized) != 0 {
t.Errorf("%s: serialized: want %x, got %x", test.name, wantSerialized, gotSerialized)
}