diff --git a/parser/transaction.go b/parser/transaction.go index 33aead4c..5821eaf8 100644 --- a/parser/transaction.go +++ b/parser/transaction.go @@ -100,6 +100,9 @@ func (tx *Transaction) ParseTransparent(data []byte) ([]byte, error) { return nil, errors.New("could not read tx_in_count") } var err error + // TODO: Duplicate/otherwise-too-many transactions are a possible DoS + // TODO: vector. At the moment we're assuming trusted input. + // See https://nvd.nist.gov/vuln/detail/CVE-2018-17144 for an example. tx.transparentInputs = make([]*txIn, txInCount) for i := 0; i < txInCount; i++ { ti := &txIn{} @@ -174,7 +177,7 @@ func (p *spend) ToCompact() *walletrpc.CompactSpend { } // output is a Sapling Output Description as described in section 7.4 of the -// Zcash protocol spec. Total size is 948. +// Zcash protocol spec. type output struct { cv []byte // 32 cmu []byte // 32 @@ -224,7 +227,7 @@ func (p *output) ToCompact() *walletrpc.CompactOutput { // joinSplit is a JoinSplit description as described in 7.2 of the Zcash // protocol spec. Its exact contents differ by transaction version and network -// upgrade level. +// upgrade level. Only version 4 is supported, no need for proofPHGR13. type joinSplit struct { vpubOld uint64 vpubNew uint64 @@ -234,12 +237,8 @@ type joinSplit struct { ephemeralKey []byte // 32 randomSeed []byte // 32 vmacs [2][]byte // 64 [N_old][32]byte - proofPHGR13 []byte // 296 - proofGroth16 []byte // 192 + proofGroth16 []byte // 192 (version 4 only) encCiphertexts [2][]byte // 1202 [N_new][601]byte - - // not actually in the format, but needed for parsing - version uint32 } func (p *joinSplit) ParseFromSlice(data []byte) ([]byte, error) { @@ -283,16 +282,8 @@ func (p *joinSplit) ParseFromSlice(data []byte) ([]byte, error) { } } - if p.version == 2 || p.version == 3 { - if !s.ReadBytes(&p.proofPHGR13, 296) { - return nil, errors.New("could not read PHGR13 proof") - } - } else if p.version >= 4 { - if !s.ReadBytes(&p.proofGroth16, 192) { - return nil, errors.New("could not read Groth16 proof") - } - } else { - return nil, errors.New("unexpected transaction version") + if !s.ReadBytes(&p.proofGroth16, 192) { + return nil, errors.New("could not read Groth16 proof") } for i := 0; i < 2; i++ { @@ -388,40 +379,36 @@ func (tx *Transaction) parseV4(data []byte) ([]byte, error) { if !s.ReadCompactSize(&spendCount) { return nil, errors.New("could not read nShieldedSpend") } - if spendCount > 0 { - tx.shieldedSpends = make([]*spend, spendCount) - for i := 0; i < spendCount; i++ { - newSpend := &spend{} - s, err = newSpend.ParseFromSlice([]byte(s), 4) - if err != nil { - return nil, errors.Wrap(err, "while parsing shielded Spend") - } - tx.shieldedSpends[i] = newSpend + tx.shieldedSpends = make([]*spend, spendCount) + for i := 0; i < spendCount; i++ { + newSpend := &spend{} + s, err = newSpend.ParseFromSlice([]byte(s), 4) + if err != nil { + return nil, errors.Wrap(err, "while parsing shielded Spend") } + tx.shieldedSpends[i] = newSpend } if !s.ReadCompactSize(&outputCount) { return nil, errors.New("could not read nShieldedOutput") } - if outputCount > 0 { - tx.shieldedOutputs = make([]*output, outputCount) - for i := 0; i < outputCount; i++ { - newOutput := &output{} - s, err = newOutput.ParseFromSlice([]byte(s), 4) - if err != nil { - return nil, errors.Wrap(err, "while parsing shielded Output") - } - tx.shieldedOutputs[i] = newOutput + tx.shieldedOutputs = make([]*output, outputCount) + for i := 0; i < outputCount; i++ { + newOutput := &output{} + s, err = newOutput.ParseFromSlice([]byte(s), 4) + if err != nil { + return nil, errors.Wrap(err, "while parsing shielded Output") } + tx.shieldedOutputs[i] = newOutput } var joinSplitCount int if !s.ReadCompactSize(&joinSplitCount) { return nil, errors.New("could not read nJoinSplit") } + tx.joinSplits = make([]*joinSplit, joinSplitCount) if joinSplitCount > 0 { - tx.joinSplits = make([]*joinSplit, joinSplitCount) for i := 0; i < joinSplitCount; i++ { - js := &joinSplit{version: 4} + js := &joinSplit{} s, err = js.ParseFromSlice([]byte(s)) if err != nil { return nil, errors.Wrap(err, "while parsing JoinSplit")