| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | package common | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"math/big" | 
					
						
							| 
									
										
										
										
											2014-12-17 12:57:35 +01:00
										 |  |  | 	"reflect" | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-11 16:23:38 +02:00
										 |  |  | type RlpEncode interface { | 
					
						
							| 
									
										
										
										
											2014-03-20 17:27:26 +01:00
										 |  |  | 	RlpEncode() []byte | 
					
						
							| 
									
										
										
										
											2014-08-11 16:23:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type RlpEncodeDecode interface { | 
					
						
							|  |  |  | 	RlpEncode | 
					
						
							| 
									
										
										
										
											2014-06-16 00:52:10 +02:00
										 |  |  | 	RlpValue() []interface{} | 
					
						
							| 
									
										
										
										
											2014-03-20 17:27:26 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-29 10:34:40 +01:00
										 |  |  | type RlpEncodable interface { | 
					
						
							|  |  |  | 	RlpData() interface{} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-19 13:19:19 +02:00
										 |  |  | func Rlp(encoder RlpEncode) []byte { | 
					
						
							|  |  |  | 	return encoder.RlpEncode() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | type RlpEncoder struct { | 
					
						
							|  |  |  | 	rlpData []byte | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func NewRlpEncoder() *RlpEncoder { | 
					
						
							|  |  |  | 	encoder := &RlpEncoder{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return encoder | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | func (coder *RlpEncoder) EncodeData(rlpData interface{}) []byte { | 
					
						
							|  |  |  | 	return Encode(rlpData) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	RlpEmptyList = 0x80 | 
					
						
							|  |  |  | 	RlpEmptyStr  = 0x40 | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-01 10:21:43 +02:00
										 |  |  | const rlpEof = -1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | func Char(c []byte) int { | 
					
						
							|  |  |  | 	if len(c) > 0 { | 
					
						
							|  |  |  | 		return int(c[0]) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-01 10:21:43 +02:00
										 |  |  | 	return rlpEof | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func DecodeWithReader(reader *bytes.Buffer) interface{} { | 
					
						
							|  |  |  | 	var slice []interface{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Read the next byte | 
					
						
							|  |  |  | 	char := Char(reader.Next(1)) | 
					
						
							|  |  |  | 	switch { | 
					
						
							| 
									
										
										
										
											2014-03-27 15:38:55 +01:00
										 |  |  | 	case char <= 0x7f: | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		return char | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case char <= 0xb7: | 
					
						
							|  |  |  | 		return reader.Next(int(char - 0x80)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case char <= 0xbf: | 
					
						
							| 
									
										
										
										
											2014-07-29 23:31:33 +02:00
										 |  |  | 		length := ReadVarInt(reader.Next(int(char - 0xb7))) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return reader.Next(int(length)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case char <= 0xf7: | 
					
						
							|  |  |  | 		length := int(char - 0xc0) | 
					
						
							|  |  |  | 		for i := 0; i < length; i++ { | 
					
						
							|  |  |  | 			obj := DecodeWithReader(reader) | 
					
						
							| 
									
										
										
										
											2014-08-01 10:21:43 +02:00
										 |  |  | 			slice = append(slice, obj) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return slice | 
					
						
							|  |  |  | 	case char <= 0xff: | 
					
						
							| 
									
										
										
										
											2014-07-29 23:31:33 +02:00
										 |  |  | 		length := ReadVarInt(reader.Next(int(char - 0xf7))) | 
					
						
							|  |  |  | 		for i := uint64(0); i < length; i++ { | 
					
						
							|  |  |  | 			obj := DecodeWithReader(reader) | 
					
						
							| 
									
										
										
										
											2014-08-01 10:21:43 +02:00
										 |  |  | 			slice = append(slice, obj) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-08-01 10:21:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return slice | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2014-08-01 10:21:43 +02:00
										 |  |  | 		panic(fmt.Sprintf("byte not supported: %q", char)) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-29 23:31:33 +02:00
										 |  |  | 	return slice | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	directRlp = big.NewInt(0x7f) | 
					
						
							|  |  |  | 	numberRlp = big.NewInt(0xb7) | 
					
						
							|  |  |  | 	zeroRlp   = big.NewInt(0x0) | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-17 12:57:35 +01:00
										 |  |  | func intlen(i int64) (length int) { | 
					
						
							|  |  |  | 	for i > 0 { | 
					
						
							|  |  |  | 		i = i >> 8 | 
					
						
							|  |  |  | 		length++ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | func Encode(object interface{}) []byte { | 
					
						
							|  |  |  | 	var buff bytes.Buffer | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if object != nil { | 
					
						
							|  |  |  | 		switch t := object.(type) { | 
					
						
							| 
									
										
										
										
											2014-02-15 01:34:18 +01:00
										 |  |  | 		case *Value: | 
					
						
							|  |  |  | 			buff.Write(Encode(t.Raw())) | 
					
						
							| 
									
										
										
										
											2014-10-29 10:34:40 +01:00
										 |  |  | 		case RlpEncodable: | 
					
						
							|  |  |  | 			buff.Write(Encode(t.RlpData())) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		// Code dup :-/ | 
					
						
							|  |  |  | 		case int: | 
					
						
							|  |  |  | 			buff.Write(Encode(big.NewInt(int64(t)))) | 
					
						
							|  |  |  | 		case uint: | 
					
						
							|  |  |  | 			buff.Write(Encode(big.NewInt(int64(t)))) | 
					
						
							|  |  |  | 		case int8: | 
					
						
							|  |  |  | 			buff.Write(Encode(big.NewInt(int64(t)))) | 
					
						
							|  |  |  | 		case int16: | 
					
						
							|  |  |  | 			buff.Write(Encode(big.NewInt(int64(t)))) | 
					
						
							|  |  |  | 		case int32: | 
					
						
							|  |  |  | 			buff.Write(Encode(big.NewInt(int64(t)))) | 
					
						
							|  |  |  | 		case int64: | 
					
						
							|  |  |  | 			buff.Write(Encode(big.NewInt(t))) | 
					
						
							|  |  |  | 		case uint16: | 
					
						
							|  |  |  | 			buff.Write(Encode(big.NewInt(int64(t)))) | 
					
						
							|  |  |  | 		case uint32: | 
					
						
							|  |  |  | 			buff.Write(Encode(big.NewInt(int64(t)))) | 
					
						
							|  |  |  | 		case uint64: | 
					
						
							|  |  |  | 			buff.Write(Encode(big.NewInt(int64(t)))) | 
					
						
							|  |  |  | 		case byte: | 
					
						
							|  |  |  | 			buff.Write(Encode(big.NewInt(int64(t)))) | 
					
						
							|  |  |  | 		case *big.Int: | 
					
						
							| 
									
										
										
										
											2015-01-08 16:37:06 +01:00
										 |  |  | 			// Not sure how this is possible while we check for nil | 
					
						
							| 
									
										
										
										
											2014-04-09 12:27:25 -04:00
										 |  |  | 			if t == nil { | 
					
						
							|  |  |  | 				buff.WriteByte(0xc0) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				buff.Write(Encode(t.Bytes())) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-09-15 15:42:12 +02:00
										 |  |  | 		case Bytes: | 
					
						
							|  |  |  | 			buff.Write(Encode([]byte(t))) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		case []byte: | 
					
						
							|  |  |  | 			if len(t) == 1 && t[0] <= 0x7f { | 
					
						
							|  |  |  | 				buff.Write(t) | 
					
						
							|  |  |  | 			} else if len(t) < 56 { | 
					
						
							|  |  |  | 				buff.WriteByte(byte(len(t) + 0x80)) | 
					
						
							|  |  |  | 				buff.Write(t) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				b := big.NewInt(int64(len(t))) | 
					
						
							|  |  |  | 				buff.WriteByte(byte(len(b.Bytes()) + 0xb7)) | 
					
						
							|  |  |  | 				buff.Write(b.Bytes()) | 
					
						
							|  |  |  | 				buff.Write(t) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case string: | 
					
						
							|  |  |  | 			buff.Write(Encode([]byte(t))) | 
					
						
							|  |  |  | 		case []interface{}: | 
					
						
							|  |  |  | 			// Inline function for writing the slice header | 
					
						
							|  |  |  | 			WriteSliceHeader := func(length int) { | 
					
						
							|  |  |  | 				if length < 56 { | 
					
						
							|  |  |  | 					buff.WriteByte(byte(length + 0xc0)) | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					b := big.NewInt(int64(length)) | 
					
						
							|  |  |  | 					buff.WriteByte(byte(len(b.Bytes()) + 0xf7)) | 
					
						
							|  |  |  | 					buff.Write(b.Bytes()) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var b bytes.Buffer | 
					
						
							|  |  |  | 			for _, val := range t { | 
					
						
							|  |  |  | 				b.Write(Encode(val)) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			WriteSliceHeader(len(b.Bytes())) | 
					
						
							|  |  |  | 			buff.Write(b.Bytes()) | 
					
						
							| 
									
										
										
										
											2014-12-17 12:57:35 +01:00
										 |  |  | 		default: | 
					
						
							|  |  |  | 			// This is how it should have been from the start | 
					
						
							|  |  |  | 			// needs refactoring (@fjl) | 
					
						
							|  |  |  | 			v := reflect.ValueOf(t) | 
					
						
							|  |  |  | 			switch v.Kind() { | 
					
						
							|  |  |  | 			case reflect.Slice: | 
					
						
							|  |  |  | 				var b bytes.Buffer | 
					
						
							|  |  |  | 				for i := 0; i < v.Len(); i++ { | 
					
						
							|  |  |  | 					b.Write(Encode(v.Index(i).Interface())) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				blen := b.Len() | 
					
						
							|  |  |  | 				if blen < 56 { | 
					
						
							|  |  |  | 					buff.WriteByte(byte(blen) + 0xc0) | 
					
						
							|  |  |  | 				} else { | 
					
						
							| 
									
										
										
										
											2014-12-18 11:39:24 +01:00
										 |  |  | 					ilen := byte(intlen(int64(blen))) | 
					
						
							|  |  |  | 					buff.WriteByte(ilen + 0xf7) | 
					
						
							|  |  |  | 					t := make([]byte, ilen) | 
					
						
							|  |  |  | 					for i := byte(0); i < ilen; i++ { | 
					
						
							|  |  |  | 						t[ilen-i-1] = byte(blen >> (i * 8)) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					buff.Write(t) | 
					
						
							| 
									
										
										
										
											2014-12-17 12:57:35 +01:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				buff.ReadFrom(&b) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		// Empty list for nil | 
					
						
							|  |  |  | 		buff.WriteByte(0xc0) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return buff.Bytes() | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-07-29 23:31:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // TODO Use a bytes.Buffer instead of a raw byte slice. | 
					
						
							|  |  |  | // Cleaner code, and use draining instead of seeking the next bytes to read | 
					
						
							|  |  |  | func Decode(data []byte, pos uint64) (interface{}, uint64) { | 
					
						
							|  |  |  | 	var slice []interface{} | 
					
						
							|  |  |  | 	char := int(data[pos]) | 
					
						
							|  |  |  | 	switch { | 
					
						
							|  |  |  | 	case char <= 0x7f: | 
					
						
							|  |  |  | 		return data[pos], pos + 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case char <= 0xb7: | 
					
						
							|  |  |  | 		b := uint64(data[pos]) - 0x80 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return data[pos+1 : pos+1+b], pos + 1 + b | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case char <= 0xbf: | 
					
						
							|  |  |  | 		b := uint64(data[pos]) - 0xb7 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		b2 := ReadVarInt(data[pos+1 : pos+1+b]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return data[pos+1+b : pos+1+b+b2], pos + 1 + b + b2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case char <= 0xf7: | 
					
						
							|  |  |  | 		b := uint64(data[pos]) - 0xc0 | 
					
						
							|  |  |  | 		prevPos := pos | 
					
						
							|  |  |  | 		pos++ | 
					
						
							|  |  |  | 		for i := uint64(0); i < b; { | 
					
						
							|  |  |  | 			var obj interface{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Get the next item in the data list and append it | 
					
						
							|  |  |  | 			obj, prevPos = Decode(data, pos) | 
					
						
							|  |  |  | 			slice = append(slice, obj) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Increment i by the amount bytes read in the previous | 
					
						
							|  |  |  | 			// read | 
					
						
							|  |  |  | 			i += (prevPos - pos) | 
					
						
							|  |  |  | 			pos = prevPos | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return slice, pos | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case char <= 0xff: | 
					
						
							|  |  |  | 		l := uint64(data[pos]) - 0xf7 | 
					
						
							|  |  |  | 		b := ReadVarInt(data[pos+1 : pos+1+l]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		pos = pos + l + 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		prevPos := b | 
					
						
							|  |  |  | 		for i := uint64(0); i < uint64(b); { | 
					
						
							|  |  |  | 			var obj interface{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			obj, prevPos = Decode(data, pos) | 
					
						
							|  |  |  | 			slice = append(slice, obj) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			i += (prevPos - pos) | 
					
						
							|  |  |  | 			pos = prevPos | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return slice, pos | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		panic(fmt.Sprintf("byte not supported: %q", char)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return slice, 0 | 
					
						
							|  |  |  | } |