consensus, core/*, params: metropolis preparation refactor
This commit is a preparation for the upcoming metropolis hardfork. It prepares the state, core and vm packages such that integration with metropolis becomes less of a hassle. * Difficulty calculation requires header instead of individual parameters * statedb.StartRecord renamed to statedb.Prepare and added Finalise method required by metropolis, which removes unwanted accounts from the state (i.e. selfdestruct) * State keeps record of destructed objects (in addition to dirty objects) * core/vm pre-compiles may now return errors * core/vm pre-compiles gas check now take the full byte slice as argument instead of just the size * core/vm now keeps several hard-fork instruction tables instead of a single instruction table and removes the need for hard-fork checks in the instructions * core/vm contains a empty restruction function which is added in preparation of metropolis write-only mode operations * Adds the bn256 curve * Adds and sets the metropolis chain config block parameters (2^64-1)
This commit is contained in:
		@@ -239,7 +239,7 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *
 | 
				
			|||||||
		return errZeroBlockTime
 | 
							return errZeroBlockTime
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Verify the block's difficulty based in it's timestamp and parent's difficulty
 | 
						// Verify the block's difficulty based in it's timestamp and parent's difficulty
 | 
				
			||||||
	expected := CalcDifficulty(chain.Config(), header.Time.Uint64(), parent.Time.Uint64(), parent.Number, parent.Difficulty)
 | 
						expected := CalcDifficulty(chain.Config(), header.Time.Uint64(), parent)
 | 
				
			||||||
	if expected.Cmp(header.Difficulty) != 0 {
 | 
						if expected.Cmp(header.Difficulty) != 0 {
 | 
				
			||||||
		return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected)
 | 
							return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -283,16 +283,19 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
 | 
					// CalcDifficulty is the difficulty adjustment algorithm. It returns
 | 
				
			||||||
// that a new block should have when created at time given the parent block's time
 | 
					// the difficulty that a new block should have when created at time
 | 
				
			||||||
// and difficulty.
 | 
					// given the parent block's time and difficulty.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// TODO (karalabe): Move the chain maker into this package and make this private!
 | 
					// TODO (karalabe): Move the chain maker into this package and make this private!
 | 
				
			||||||
func CalcDifficulty(config *params.ChainConfig, time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
 | 
					func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int {
 | 
				
			||||||
	if config.IsHomestead(new(big.Int).Add(parentNumber, common.Big1)) {
 | 
						next := new(big.Int).Add(parent.Number, common.Big1)
 | 
				
			||||||
		return calcDifficultyHomestead(time, parentTime, parentNumber, parentDiff)
 | 
						switch {
 | 
				
			||||||
 | 
						case config.IsHomestead(next):
 | 
				
			||||||
 | 
							return calcDifficultyHomestead(time, parent)
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return calcDifficultyFrontier(time, parent)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return calcDifficultyFrontier(time, parentTime, parentNumber, parentDiff)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Some weird constants to avoid constant memory allocs for them.
 | 
					// Some weird constants to avoid constant memory allocs for them.
 | 
				
			||||||
@@ -305,15 +308,15 @@ var (
 | 
				
			|||||||
// calcDifficultyHomestead is the difficulty adjustment algorithm. It returns
 | 
					// calcDifficultyHomestead is the difficulty adjustment algorithm. It returns
 | 
				
			||||||
// the difficulty that a new block should have when created at time given the
 | 
					// the difficulty that a new block should have when created at time given the
 | 
				
			||||||
// parent block's time and difficulty. The calculation uses the Homestead rules.
 | 
					// parent block's time and difficulty. The calculation uses the Homestead rules.
 | 
				
			||||||
func calcDifficultyHomestead(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
 | 
					func calcDifficultyHomestead(time uint64, parent *types.Header) *big.Int {
 | 
				
			||||||
	// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.mediawiki
 | 
						// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.mediawiki
 | 
				
			||||||
	// algorithm:
 | 
						// algorithm:
 | 
				
			||||||
	// diff = (parent_diff +
 | 
						// diff = (parent_diff +
 | 
				
			||||||
	//         (parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
 | 
						//         (parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
 | 
				
			||||||
	//        ) + 2^(periodCount - 2)
 | 
						//        ) + 2^(periodCount - 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bigTime := new(big.Int).SetUint64(time)
 | 
						bigTime := new(big.Int).Set(parent.Time)
 | 
				
			||||||
	bigParentTime := new(big.Int).SetUint64(parentTime)
 | 
						bigParentTime := new(big.Int).Set(parent.Time)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// holds intermediate values to make the algo easier to read & audit
 | 
						// holds intermediate values to make the algo easier to read & audit
 | 
				
			||||||
	x := new(big.Int)
 | 
						x := new(big.Int)
 | 
				
			||||||
@@ -329,16 +332,16 @@ func calcDifficultyHomestead(time, parentTime uint64, parentNumber, parentDiff *
 | 
				
			|||||||
		x.Set(bigMinus99)
 | 
							x.Set(bigMinus99)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// (parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
 | 
						// (parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
 | 
				
			||||||
	y.Div(parentDiff, params.DifficultyBoundDivisor)
 | 
						y.Div(parent.Difficulty, params.DifficultyBoundDivisor)
 | 
				
			||||||
	x.Mul(y, x)
 | 
						x.Mul(y, x)
 | 
				
			||||||
	x.Add(parentDiff, x)
 | 
						x.Add(parent.Difficulty, x)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// minimum difficulty can ever be (before exponential factor)
 | 
						// minimum difficulty can ever be (before exponential factor)
 | 
				
			||||||
	if x.Cmp(params.MinimumDifficulty) < 0 {
 | 
						if x.Cmp(params.MinimumDifficulty) < 0 {
 | 
				
			||||||
		x.Set(params.MinimumDifficulty)
 | 
							x.Set(params.MinimumDifficulty)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// for the exponential factor
 | 
						// for the exponential factor
 | 
				
			||||||
	periodCount := new(big.Int).Add(parentNumber, common.Big1)
 | 
						periodCount := new(big.Int).Add(parent.Number, common.Big1)
 | 
				
			||||||
	periodCount.Div(periodCount, expDiffPeriod)
 | 
						periodCount.Div(periodCount, expDiffPeriod)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// the exponential factor, commonly referred to as "the bomb"
 | 
						// the exponential factor, commonly referred to as "the bomb"
 | 
				
			||||||
@@ -354,25 +357,25 @@ func calcDifficultyHomestead(time, parentTime uint64, parentNumber, parentDiff *
 | 
				
			|||||||
// calcDifficultyFrontier is the difficulty adjustment algorithm. It returns the
 | 
					// calcDifficultyFrontier is the difficulty adjustment algorithm. It returns the
 | 
				
			||||||
// difficulty that a new block should have when created at time given the parent
 | 
					// difficulty that a new block should have when created at time given the parent
 | 
				
			||||||
// block's time and difficulty. The calculation uses the Frontier rules.
 | 
					// block's time and difficulty. The calculation uses the Frontier rules.
 | 
				
			||||||
func calcDifficultyFrontier(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
 | 
					func calcDifficultyFrontier(time uint64, parent *types.Header) *big.Int {
 | 
				
			||||||
	diff := new(big.Int)
 | 
						diff := new(big.Int)
 | 
				
			||||||
	adjust := new(big.Int).Div(parentDiff, params.DifficultyBoundDivisor)
 | 
						adjust := new(big.Int).Div(parent.Difficulty, params.DifficultyBoundDivisor)
 | 
				
			||||||
	bigTime := new(big.Int)
 | 
						bigTime := new(big.Int)
 | 
				
			||||||
	bigParentTime := new(big.Int)
 | 
						bigParentTime := new(big.Int)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bigTime.SetUint64(time)
 | 
						bigTime.SetUint64(time)
 | 
				
			||||||
	bigParentTime.SetUint64(parentTime)
 | 
						bigParentTime.Set(parent.Time)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if bigTime.Sub(bigTime, bigParentTime).Cmp(params.DurationLimit) < 0 {
 | 
						if bigTime.Sub(bigTime, bigParentTime).Cmp(params.DurationLimit) < 0 {
 | 
				
			||||||
		diff.Add(parentDiff, adjust)
 | 
							diff.Add(parent.Difficulty, adjust)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		diff.Sub(parentDiff, adjust)
 | 
							diff.Sub(parent.Difficulty, adjust)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if diff.Cmp(params.MinimumDifficulty) < 0 {
 | 
						if diff.Cmp(params.MinimumDifficulty) < 0 {
 | 
				
			||||||
		diff.Set(params.MinimumDifficulty)
 | 
							diff.Set(params.MinimumDifficulty)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	periodCount := new(big.Int).Add(parentNumber, common.Big1)
 | 
						periodCount := new(big.Int).Add(parent.Number, common.Big1)
 | 
				
			||||||
	periodCount.Div(periodCount, expDiffPeriod)
 | 
						periodCount.Div(periodCount, expDiffPeriod)
 | 
				
			||||||
	if periodCount.Cmp(common.Big1) > 0 {
 | 
						if periodCount.Cmp(common.Big1) > 0 {
 | 
				
			||||||
		// diff = diff + 2^(periodCount - 2)
 | 
							// diff = diff + 2^(periodCount - 2)
 | 
				
			||||||
@@ -434,8 +437,7 @@ func (ethash *Ethash) Prepare(chain consensus.ChainReader, header *types.Header)
 | 
				
			|||||||
	if parent == nil {
 | 
						if parent == nil {
 | 
				
			||||||
		return consensus.ErrUnknownAncestor
 | 
							return consensus.ErrUnknownAncestor
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	header.Difficulty = CalcDifficulty(chain.Config(), header.Time.Uint64(),
 | 
						header.Difficulty = CalcDifficulty(chain.Config(), header.Time.Uint64(), parent)
 | 
				
			||||||
		parent.Time.Uint64(), parent.Number, parent.Difficulty)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@ import (
 | 
				
			|||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/common/math"
 | 
						"github.com/ethereum/go-ethereum/common/math"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/core/types"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/params"
 | 
						"github.com/ethereum/go-ethereum/params"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -71,7 +72,11 @@ func TestCalcDifficulty(t *testing.T) {
 | 
				
			|||||||
	config := ¶ms.ChainConfig{HomesteadBlock: big.NewInt(1150000)}
 | 
						config := ¶ms.ChainConfig{HomesteadBlock: big.NewInt(1150000)}
 | 
				
			||||||
	for name, test := range tests {
 | 
						for name, test := range tests {
 | 
				
			||||||
		number := new(big.Int).Sub(test.CurrentBlocknumber, big.NewInt(1))
 | 
							number := new(big.Int).Sub(test.CurrentBlocknumber, big.NewInt(1))
 | 
				
			||||||
		diff := CalcDifficulty(config, test.CurrentTimestamp, test.ParentTimestamp, number, test.ParentDifficulty)
 | 
							diff := CalcDifficulty(config, test.CurrentTimestamp, &types.Header{
 | 
				
			||||||
 | 
								Number:     number,
 | 
				
			||||||
 | 
								Time:       test.ParentTimestamp,
 | 
				
			||||||
 | 
								Difficulty: test.ParentDifficulty,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
		if diff.Cmp(test.CurrentDifficulty) != 0 {
 | 
							if diff.Cmp(test.CurrentDifficulty) != 0 {
 | 
				
			||||||
			t.Error(name, "failed. Expected", test.CurrentDifficulty, "and calculated", diff)
 | 
								t.Error(name, "failed. Expected", test.CurrentDifficulty, "and calculated", diff)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -84,7 +84,7 @@ func (b *BlockGen) AddTx(tx *types.Transaction) {
 | 
				
			|||||||
	if b.gasPool == nil {
 | 
						if b.gasPool == nil {
 | 
				
			||||||
		b.SetCoinbase(common.Address{})
 | 
							b.SetCoinbase(common.Address{})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	b.statedb.StartRecord(tx.Hash(), common.Hash{}, len(b.txs))
 | 
						b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs))
 | 
				
			||||||
	receipt, _, err := ApplyTransaction(b.config, nil, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{})
 | 
						receipt, _, err := ApplyTransaction(b.config, nil, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		panic(err)
 | 
							panic(err)
 | 
				
			||||||
@@ -142,7 +142,7 @@ func (b *BlockGen) OffsetTime(seconds int64) {
 | 
				
			|||||||
	if b.header.Time.Cmp(b.parent.Header().Time) <= 0 {
 | 
						if b.header.Time.Cmp(b.parent.Header().Time) <= 0 {
 | 
				
			||||||
		panic("block time out of range")
 | 
							panic("block time out of range")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	b.header.Difficulty = ethash.CalcDifficulty(b.config, b.header.Time.Uint64(), b.parent.Time().Uint64(), b.parent.Number(), b.parent.Difficulty())
 | 
						b.header.Difficulty = ethash.CalcDifficulty(b.config, b.header.Time.Uint64(), b.parent.Header())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GenerateChain creates a chain of n blocks. The first block's
 | 
					// GenerateChain creates a chain of n blocks. The first block's
 | 
				
			||||||
@@ -209,15 +209,23 @@ func makeHeader(config *params.ChainConfig, parent *types.Block, state *state.St
 | 
				
			|||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		time = new(big.Int).Add(parent.Time(), big.NewInt(10)) // block time is fixed at 10 seconds
 | 
							time = new(big.Int).Add(parent.Time(), big.NewInt(10)) // block time is fixed at 10 seconds
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						parentHeader := parent.Header()
 | 
				
			||||||
 | 
						// adjust the parent time
 | 
				
			||||||
 | 
						parentHeader.Time = new(big.Int).Sub(time, big.NewInt(10))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &types.Header{
 | 
						return &types.Header{
 | 
				
			||||||
		Root:       state.IntermediateRoot(config.IsEIP158(parent.Number())),
 | 
							Root:       state.IntermediateRoot(config.IsEIP158(parent.Number())),
 | 
				
			||||||
		ParentHash: parent.Hash(),
 | 
							ParentHash: parent.Hash(),
 | 
				
			||||||
		Coinbase:   parent.Coinbase(),
 | 
							Coinbase:   parent.Coinbase(),
 | 
				
			||||||
		Difficulty: ethash.CalcDifficulty(config, time.Uint64(), new(big.Int).Sub(time, big.NewInt(10)).Uint64(), parent.Number(), parent.Difficulty()),
 | 
							Difficulty: ethash.CalcDifficulty(config, time.Uint64(), &types.Header{
 | 
				
			||||||
		GasLimit:   CalcGasLimit(parent),
 | 
								Number:     parent.Number(),
 | 
				
			||||||
		GasUsed:    new(big.Int),
 | 
								Time:       new(big.Int).Sub(time, big.NewInt(10)),
 | 
				
			||||||
		Number:     new(big.Int).Add(parent.Number(), common.Big1),
 | 
								Difficulty: parent.Difficulty(),
 | 
				
			||||||
		Time:       time,
 | 
							}),
 | 
				
			||||||
 | 
							GasLimit: CalcGasLimit(parent),
 | 
				
			||||||
 | 
							GasUsed:  new(big.Int),
 | 
				
			||||||
 | 
							Number:   new(big.Int).Add(parent.Number(), common.Big1),
 | 
				
			||||||
 | 
							Time:     time,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,8 +62,9 @@ type StateDB struct {
 | 
				
			|||||||
	codeSizeCache *lru.Cache
 | 
						codeSizeCache *lru.Cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// This map holds 'live' objects, which will get modified while processing a state transition.
 | 
						// This map holds 'live' objects, which will get modified while processing a state transition.
 | 
				
			||||||
	stateObjects      map[common.Address]*stateObject
 | 
						stateObjects           map[common.Address]*stateObject
 | 
				
			||||||
	stateObjectsDirty map[common.Address]struct{}
 | 
						stateObjectsDirty      map[common.Address]struct{}
 | 
				
			||||||
 | 
						stateObjectsDestructed map[common.Address]struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The refund counter, also used by state transitioning.
 | 
						// The refund counter, also used by state transitioning.
 | 
				
			||||||
	refund *big.Int
 | 
						refund *big.Int
 | 
				
			||||||
@@ -92,14 +93,15 @@ func New(root common.Hash, db ethdb.Database) (*StateDB, error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	csc, _ := lru.New(codeSizeCacheSize)
 | 
						csc, _ := lru.New(codeSizeCacheSize)
 | 
				
			||||||
	return &StateDB{
 | 
						return &StateDB{
 | 
				
			||||||
		db:                db,
 | 
							db:                     db,
 | 
				
			||||||
		trie:              tr,
 | 
							trie:                   tr,
 | 
				
			||||||
		codeSizeCache:     csc,
 | 
							codeSizeCache:          csc,
 | 
				
			||||||
		stateObjects:      make(map[common.Address]*stateObject),
 | 
							stateObjects:           make(map[common.Address]*stateObject),
 | 
				
			||||||
		stateObjectsDirty: make(map[common.Address]struct{}),
 | 
							stateObjectsDirty:      make(map[common.Address]struct{}),
 | 
				
			||||||
		refund:            new(big.Int),
 | 
							stateObjectsDestructed: make(map[common.Address]struct{}),
 | 
				
			||||||
		logs:              make(map[common.Hash][]*types.Log),
 | 
							refund:                 new(big.Int),
 | 
				
			||||||
		preimages:         make(map[common.Hash][]byte),
 | 
							logs:                   make(map[common.Hash][]*types.Log),
 | 
				
			||||||
 | 
							preimages:              make(map[common.Hash][]byte),
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -114,14 +116,15 @@ func (self *StateDB) New(root common.Hash) (*StateDB, error) {
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return &StateDB{
 | 
						return &StateDB{
 | 
				
			||||||
		db:                self.db,
 | 
							db:                     self.db,
 | 
				
			||||||
		trie:              tr,
 | 
							trie:                   tr,
 | 
				
			||||||
		codeSizeCache:     self.codeSizeCache,
 | 
							codeSizeCache:          self.codeSizeCache,
 | 
				
			||||||
		stateObjects:      make(map[common.Address]*stateObject),
 | 
							stateObjects:           make(map[common.Address]*stateObject),
 | 
				
			||||||
		stateObjectsDirty: make(map[common.Address]struct{}),
 | 
							stateObjectsDirty:      make(map[common.Address]struct{}),
 | 
				
			||||||
		refund:            new(big.Int),
 | 
							stateObjectsDestructed: make(map[common.Address]struct{}),
 | 
				
			||||||
		logs:              make(map[common.Hash][]*types.Log),
 | 
							refund:                 new(big.Int),
 | 
				
			||||||
		preimages:         make(map[common.Hash][]byte),
 | 
							logs:                   make(map[common.Hash][]*types.Log),
 | 
				
			||||||
 | 
							preimages:              make(map[common.Hash][]byte),
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -138,6 +141,7 @@ func (self *StateDB) Reset(root common.Hash) error {
 | 
				
			|||||||
	self.trie = tr
 | 
						self.trie = tr
 | 
				
			||||||
	self.stateObjects = make(map[common.Address]*stateObject)
 | 
						self.stateObjects = make(map[common.Address]*stateObject)
 | 
				
			||||||
	self.stateObjectsDirty = make(map[common.Address]struct{})
 | 
						self.stateObjectsDirty = make(map[common.Address]struct{})
 | 
				
			||||||
 | 
						self.stateObjectsDestructed = make(map[common.Address]struct{})
 | 
				
			||||||
	self.thash = common.Hash{}
 | 
						self.thash = common.Hash{}
 | 
				
			||||||
	self.bhash = common.Hash{}
 | 
						self.bhash = common.Hash{}
 | 
				
			||||||
	self.txIndex = 0
 | 
						self.txIndex = 0
 | 
				
			||||||
@@ -173,12 +177,6 @@ func (self *StateDB) pushTrie(t *trie.SecureTrie) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateDB) StartRecord(thash, bhash common.Hash, ti int) {
 | 
					 | 
				
			||||||
	self.thash = thash
 | 
					 | 
				
			||||||
	self.bhash = bhash
 | 
					 | 
				
			||||||
	self.txIndex = ti
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (self *StateDB) AddLog(log *types.Log) {
 | 
					func (self *StateDB) AddLog(log *types.Log) {
 | 
				
			||||||
	self.journal = append(self.journal, addLogChange{txhash: self.thash})
 | 
						self.journal = append(self.journal, addLogChange{txhash: self.thash})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -510,21 +508,25 @@ func (self *StateDB) Copy() *StateDB {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Copy all the basic fields, initialize the memory ones
 | 
						// Copy all the basic fields, initialize the memory ones
 | 
				
			||||||
	state := &StateDB{
 | 
						state := &StateDB{
 | 
				
			||||||
		db:                self.db,
 | 
							db:                     self.db,
 | 
				
			||||||
		trie:              self.trie,
 | 
							trie:                   self.trie,
 | 
				
			||||||
		pastTries:         self.pastTries,
 | 
							pastTries:              self.pastTries,
 | 
				
			||||||
		codeSizeCache:     self.codeSizeCache,
 | 
							codeSizeCache:          self.codeSizeCache,
 | 
				
			||||||
		stateObjects:      make(map[common.Address]*stateObject, len(self.stateObjectsDirty)),
 | 
							stateObjects:           make(map[common.Address]*stateObject, len(self.stateObjectsDirty)),
 | 
				
			||||||
		stateObjectsDirty: make(map[common.Address]struct{}, len(self.stateObjectsDirty)),
 | 
							stateObjectsDirty:      make(map[common.Address]struct{}, len(self.stateObjectsDirty)),
 | 
				
			||||||
		refund:            new(big.Int).Set(self.refund),
 | 
							stateObjectsDestructed: make(map[common.Address]struct{}, len(self.stateObjectsDestructed)),
 | 
				
			||||||
		logs:              make(map[common.Hash][]*types.Log, len(self.logs)),
 | 
							refund:                 new(big.Int).Set(self.refund),
 | 
				
			||||||
		logSize:           self.logSize,
 | 
							logs:                   make(map[common.Hash][]*types.Log, len(self.logs)),
 | 
				
			||||||
		preimages:         make(map[common.Hash][]byte),
 | 
							logSize:                self.logSize,
 | 
				
			||||||
 | 
							preimages:              make(map[common.Hash][]byte),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Copy the dirty states, logs, and preimages
 | 
						// Copy the dirty states, logs, and preimages
 | 
				
			||||||
	for addr := range self.stateObjectsDirty {
 | 
						for addr := range self.stateObjectsDirty {
 | 
				
			||||||
		state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state, state.MarkStateObjectDirty)
 | 
							state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state, state.MarkStateObjectDirty)
 | 
				
			||||||
		state.stateObjectsDirty[addr] = struct{}{}
 | 
							state.stateObjectsDirty[addr] = struct{}{}
 | 
				
			||||||
 | 
							if self.stateObjects[addr].suicided {
 | 
				
			||||||
 | 
								state.stateObjectsDestructed[addr] = struct{}{}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for hash, logs := range self.logs {
 | 
						for hash, logs := range self.logs {
 | 
				
			||||||
		state.logs[hash] = make([]*types.Log, len(logs))
 | 
							state.logs[hash] = make([]*types.Log, len(logs))
 | 
				
			||||||
@@ -590,6 +592,27 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
 | 
				
			|||||||
	return s.trie.Hash()
 | 
						return s.trie.Hash()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Prepare sets the current transaction hash and index and block hash which is
 | 
				
			||||||
 | 
					// used when the EVM emits new state logs.
 | 
				
			||||||
 | 
					func (self *StateDB) Prepare(thash, bhash common.Hash, ti int) {
 | 
				
			||||||
 | 
						self.thash = thash
 | 
				
			||||||
 | 
						self.bhash = bhash
 | 
				
			||||||
 | 
						self.txIndex = ti
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Finalise finalises the state by removing the self destructed objects
 | 
				
			||||||
 | 
					// in the current stateObjectsDestructed buffer and clears the journal
 | 
				
			||||||
 | 
					// as well as the refunds.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Please note that Finalise is used by EIP#98 and is used instead of
 | 
				
			||||||
 | 
					// IntermediateRoot.
 | 
				
			||||||
 | 
					func (s *StateDB) Finalise() {
 | 
				
			||||||
 | 
						for addr := range s.stateObjectsDestructed {
 | 
				
			||||||
 | 
							s.deleteStateObject(s.stateObjects[addr])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						s.clearJournalAndRefund()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeleteSuicides flags the suicided objects for deletion so that it
 | 
					// DeleteSuicides flags the suicided objects for deletion so that it
 | 
				
			||||||
// won't be referenced again when called / queried up on.
 | 
					// won't be referenced again when called / queried up on.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,7 +69,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	// Iterate over and process the individual transactions
 | 
						// Iterate over and process the individual transactions
 | 
				
			||||||
	for i, tx := range block.Transactions() {
 | 
						for i, tx := range block.Transactions() {
 | 
				
			||||||
		statedb.StartRecord(tx.Hash(), block.Hash(), i)
 | 
							statedb.Prepare(tx.Hash(), block.Hash(), i)
 | 
				
			||||||
		receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, totalUsedGas, cfg)
 | 
							receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, totalUsedGas, cfg)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, nil, nil, err
 | 
								return nil, nil, nil, err
 | 
				
			||||||
@@ -107,7 +107,8 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common
 | 
				
			|||||||
	usedGas.Add(usedGas, gas)
 | 
						usedGas.Add(usedGas, gas)
 | 
				
			||||||
	// Create a new receipt for the transaction, storing the intermediate root and gas used by the tx
 | 
						// Create a new receipt for the transaction, storing the intermediate root and gas used by the tx
 | 
				
			||||||
	// based on the eip phase, we're passing wether the root touch-delete accounts.
 | 
						// based on the eip phase, we're passing wether the root touch-delete accounts.
 | 
				
			||||||
	receipt := types.NewReceipt(statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes(), usedGas)
 | 
						root := statedb.IntermediateRoot(config.IsEIP158(header.Number))
 | 
				
			||||||
 | 
						receipt := types.NewReceipt(root.Bytes(), usedGas)
 | 
				
			||||||
	receipt.TxHash = tx.Hash()
 | 
						receipt.TxHash = tx.Hash()
 | 
				
			||||||
	receipt.GasUsed = new(big.Int).Set(gas)
 | 
						receipt.GasUsed = new(big.Int).Set(gas)
 | 
				
			||||||
	// if the transaction created a contract, store the creation address in the receipt.
 | 
						// if the transaction created a contract, store the creation address in the receipt.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,7 +27,12 @@ import (
 | 
				
			|||||||
	"github.com/ethereum/go-ethereum/params"
 | 
						"github.com/ethereum/go-ethereum/params"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var ErrInvalidChainId = errors.New("invalid chaid id for signer")
 | 
					var (
 | 
				
			||||||
 | 
						ErrInvalidChainId = errors.New("invalid chaid id for signer")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						errAbstractSigner     = errors.New("abstract signer")
 | 
				
			||||||
 | 
						abstractSignerAddress = common.HexToAddress("ffffffffffffffffffffffffffffffffffffff")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// sigCache is used to cache the derived sender and contains
 | 
					// sigCache is used to cache the derived sender and contains
 | 
				
			||||||
// the signer used to derive it.
 | 
					// the signer used to derive it.
 | 
				
			||||||
@@ -103,6 +108,17 @@ type Signer interface {
 | 
				
			|||||||
	Equal(Signer) bool
 | 
						Equal(Signer) bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					// WithSignature returns a new transaction with the given signature. This signature
 | 
				
			||||||
 | 
					// needs to be in the [R || S || V] format where V is 0 or 1.
 | 
				
			||||||
 | 
					func (s EIP86Signer) WithSignature(tx *Transaction, sig []byte) (*Transaction, error) {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Hash returns the hash to be signed by the sender.
 | 
				
			||||||
 | 
					// It does not uniquely identify the transaction.
 | 
				
			||||||
 | 
					func (s EIP86Signer) Hash(tx *Transaction) common.Hash {}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EIP155Transaction implements TransactionInterface using the
 | 
					// EIP155Transaction implements TransactionInterface using the
 | 
				
			||||||
// EIP155 rules
 | 
					// EIP155 rules
 | 
				
			||||||
type EIP155Signer struct {
 | 
					type EIP155Signer struct {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,7 @@ package vm
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"crypto/sha256"
 | 
						"crypto/sha256"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
	"math/big"
 | 
						"math/big"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/common"
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
@@ -27,15 +28,17 @@ import (
 | 
				
			|||||||
	"golang.org/x/crypto/ripemd160"
 | 
						"golang.org/x/crypto/ripemd160"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var errBadPrecompileInput = errors.New("bad pre compile input")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Precompiled contract is the basic interface for native Go contracts. The implementation
 | 
					// Precompiled contract is the basic interface for native Go contracts. The implementation
 | 
				
			||||||
// requires a deterministic gas count based on the input size of the Run method of the
 | 
					// requires a deterministic gas count based on the input size of the Run method of the
 | 
				
			||||||
// contract.
 | 
					// contract.
 | 
				
			||||||
type PrecompiledContract interface {
 | 
					type PrecompiledContract interface {
 | 
				
			||||||
	RequiredGas(inputSize int) uint64 // RequiredPrice calculates the contract gas use
 | 
						RequiredGas(input []byte) uint64  // RequiredPrice calculates the contract gas use
 | 
				
			||||||
	Run(input []byte) []byte          // Run runs the precompiled contract
 | 
						Run(input []byte) ([]byte, error) // Run runs the precompiled contract
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Precompiled contains the default set of ethereum contracts
 | 
					// PrecompiledContracts contains the default set of ethereum contracts
 | 
				
			||||||
var PrecompiledContracts = map[common.Address]PrecompiledContract{
 | 
					var PrecompiledContracts = map[common.Address]PrecompiledContract{
 | 
				
			||||||
	common.BytesToAddress([]byte{1}): &ecrecover{},
 | 
						common.BytesToAddress([]byte{1}): &ecrecover{},
 | 
				
			||||||
	common.BytesToAddress([]byte{2}): &sha256hash{},
 | 
						common.BytesToAddress([]byte{2}): &sha256hash{},
 | 
				
			||||||
@@ -45,11 +48,9 @@ var PrecompiledContracts = map[common.Address]PrecompiledContract{
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// RunPrecompile runs and evaluate the output of a precompiled contract defined in contracts.go
 | 
					// RunPrecompile runs and evaluate the output of a precompiled contract defined in contracts.go
 | 
				
			||||||
func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) {
 | 
					func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) {
 | 
				
			||||||
	gas := p.RequiredGas(len(input))
 | 
						gas := p.RequiredGas(input)
 | 
				
			||||||
	if contract.UseGas(gas) {
 | 
						if contract.UseGas(gas) {
 | 
				
			||||||
		ret = p.Run(input)
 | 
							return p.Run(input)
 | 
				
			||||||
 | 
					 | 
				
			||||||
		return ret, nil
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		return nil, ErrOutOfGas
 | 
							return nil, ErrOutOfGas
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -58,11 +59,11 @@ func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contr
 | 
				
			|||||||
// ECRECOVER implemented as a native contract
 | 
					// ECRECOVER implemented as a native contract
 | 
				
			||||||
type ecrecover struct{}
 | 
					type ecrecover struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *ecrecover) RequiredGas(inputSize int) uint64 {
 | 
					func (c *ecrecover) RequiredGas(input []byte) uint64 {
 | 
				
			||||||
	return params.EcrecoverGas
 | 
						return params.EcrecoverGas
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *ecrecover) Run(in []byte) []byte {
 | 
					func (c *ecrecover) Run(in []byte) ([]byte, error) {
 | 
				
			||||||
	const ecRecoverInputLength = 128
 | 
						const ecRecoverInputLength = 128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	in = common.RightPadBytes(in, ecRecoverInputLength)
 | 
						in = common.RightPadBytes(in, ecRecoverInputLength)
 | 
				
			||||||
@@ -76,18 +77,18 @@ func (c *ecrecover) Run(in []byte) []byte {
 | 
				
			|||||||
	// tighter sig s values in homestead only apply to tx sigs
 | 
						// tighter sig s values in homestead only apply to tx sigs
 | 
				
			||||||
	if !allZero(in[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) {
 | 
						if !allZero(in[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) {
 | 
				
			||||||
		log.Trace("ECRECOVER error: v, r or s value invalid")
 | 
							log.Trace("ECRECOVER error: v, r or s value invalid")
 | 
				
			||||||
		return nil
 | 
							return nil, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// v needs to be at the end for libsecp256k1
 | 
						// v needs to be at the end for libsecp256k1
 | 
				
			||||||
	pubKey, err := crypto.Ecrecover(in[:32], append(in[64:128], v))
 | 
						pubKey, err := crypto.Ecrecover(in[:32], append(in[64:128], v))
 | 
				
			||||||
	// make sure the public key is a valid one
 | 
						// make sure the public key is a valid one
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Trace("ECRECOVER failed", "err", err)
 | 
							log.Trace("ECRECOVER failed", "err", err)
 | 
				
			||||||
		return nil
 | 
							return nil, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// the first byte of pubkey is bitcoin heritage
 | 
						// the first byte of pubkey is bitcoin heritage
 | 
				
			||||||
	return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32)
 | 
						return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SHA256 implemented as a native contract
 | 
					// SHA256 implemented as a native contract
 | 
				
			||||||
@@ -97,12 +98,12 @@ type sha256hash struct{}
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
// This method does not require any overflow checking as the input size gas costs
 | 
					// This method does not require any overflow checking as the input size gas costs
 | 
				
			||||||
// required for anything significant is so high it's impossible to pay for.
 | 
					// required for anything significant is so high it's impossible to pay for.
 | 
				
			||||||
func (c *sha256hash) RequiredGas(inputSize int) uint64 {
 | 
					func (c *sha256hash) RequiredGas(input []byte) uint64 {
 | 
				
			||||||
	return uint64(inputSize+31)/32*params.Sha256WordGas + params.Sha256Gas
 | 
						return uint64(len(input)+31)/32*params.Sha256WordGas + params.Sha256Gas
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
func (c *sha256hash) Run(in []byte) []byte {
 | 
					func (c *sha256hash) Run(in []byte) ([]byte, error) {
 | 
				
			||||||
	h := sha256.Sum256(in)
 | 
						h := sha256.Sum256(in)
 | 
				
			||||||
	return h[:]
 | 
						return h[:], nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RIPMED160 implemented as a native contract
 | 
					// RIPMED160 implemented as a native contract
 | 
				
			||||||
@@ -112,13 +113,13 @@ type ripemd160hash struct{}
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
// This method does not require any overflow checking as the input size gas costs
 | 
					// This method does not require any overflow checking as the input size gas costs
 | 
				
			||||||
// required for anything significant is so high it's impossible to pay for.
 | 
					// required for anything significant is so high it's impossible to pay for.
 | 
				
			||||||
func (c *ripemd160hash) RequiredGas(inputSize int) uint64 {
 | 
					func (c *ripemd160hash) RequiredGas(input []byte) uint64 {
 | 
				
			||||||
	return uint64(inputSize+31)/32*params.Ripemd160WordGas + params.Ripemd160Gas
 | 
						return uint64(len(input)+31)/32*params.Ripemd160WordGas + params.Ripemd160Gas
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
func (c *ripemd160hash) Run(in []byte) []byte {
 | 
					func (c *ripemd160hash) Run(in []byte) ([]byte, error) {
 | 
				
			||||||
	ripemd := ripemd160.New()
 | 
						ripemd := ripemd160.New()
 | 
				
			||||||
	ripemd.Write(in)
 | 
						ripemd.Write(in)
 | 
				
			||||||
	return common.LeftPadBytes(ripemd.Sum(nil), 32)
 | 
						return common.LeftPadBytes(ripemd.Sum(nil), 32), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// data copy implemented as a native contract
 | 
					// data copy implemented as a native contract
 | 
				
			||||||
@@ -128,9 +129,9 @@ type dataCopy struct{}
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
// This method does not require any overflow checking as the input size gas costs
 | 
					// This method does not require any overflow checking as the input size gas costs
 | 
				
			||||||
// required for anything significant is so high it's impossible to pay for.
 | 
					// required for anything significant is so high it's impossible to pay for.
 | 
				
			||||||
func (c *dataCopy) RequiredGas(inputSize int) uint64 {
 | 
					func (c *dataCopy) RequiredGas(input []byte) uint64 {
 | 
				
			||||||
	return uint64(inputSize+31)/32*params.IdentityWordGas + params.IdentityGas
 | 
						return uint64(len(input)+31)/32*params.IdentityWordGas + params.IdentityGas
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
func (c *dataCopy) Run(in []byte) []byte {
 | 
					func (c *dataCopy) Run(in []byte) ([]byte, error) {
 | 
				
			||||||
	return in
 | 
						return in, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								core/vm/contracts_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								core/vm/contracts_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					package vm
 | 
				
			||||||
@@ -33,7 +33,20 @@ type (
 | 
				
			|||||||
	GetHashFunc func(uint64) common.Hash
 | 
						GetHashFunc func(uint64) common.Hash
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Context provides the EVM with auxiliary information. Once provided it shouldn't be modified.
 | 
					// run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter.
 | 
				
			||||||
 | 
					func run(evm *EVM, snapshot int, contract *Contract, input []byte) ([]byte, error) {
 | 
				
			||||||
 | 
						if contract.CodeAddr != nil {
 | 
				
			||||||
 | 
							precompiledContracts := PrecompiledContracts
 | 
				
			||||||
 | 
							if p := precompiledContracts[*contract.CodeAddr]; p != nil {
 | 
				
			||||||
 | 
								return RunPrecompiledContract(p, input, contract)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return evm.interpreter.Run(snapshot, contract, input)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Context provides the EVM with auxiliary information. Once provided
 | 
				
			||||||
 | 
					// it shouldn't be modified.
 | 
				
			||||||
type Context struct {
 | 
					type Context struct {
 | 
				
			||||||
	// CanTransfer returns whether the account contains
 | 
						// CanTransfer returns whether the account contains
 | 
				
			||||||
	// sufficient ether to transfer the value
 | 
						// sufficient ether to transfer the value
 | 
				
			||||||
@@ -55,7 +68,13 @@ type Context struct {
 | 
				
			|||||||
	Difficulty  *big.Int       // Provides information for DIFFICULTY
 | 
						Difficulty  *big.Int       // Provides information for DIFFICULTY
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EVM provides information about external sources for the EVM
 | 
					// EVM is the Ethereum Virtual Machine base object and provides
 | 
				
			||||||
 | 
					// the necessary tools to run a contract on the given state with
 | 
				
			||||||
 | 
					// the provided context. It should be noted that any error
 | 
				
			||||||
 | 
					// generated through any of the calls should be considered a
 | 
				
			||||||
 | 
					// revert-state-and-consume-all-gas operation, no checks on
 | 
				
			||||||
 | 
					// specific errors should ever be performed. The interpreter makes
 | 
				
			||||||
 | 
					// sure that any errors generated are to be considered faulty code.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// The EVM should never be reused and is not thread safe.
 | 
					// The EVM should never be reused and is not thread safe.
 | 
				
			||||||
type EVM struct {
 | 
					type EVM struct {
 | 
				
			||||||
@@ -68,6 +87,8 @@ type EVM struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// chainConfig contains information about the current chain
 | 
						// chainConfig contains information about the current chain
 | 
				
			||||||
	chainConfig *params.ChainConfig
 | 
						chainConfig *params.ChainConfig
 | 
				
			||||||
 | 
						// chain rules contains the chain rules for the current epoch
 | 
				
			||||||
 | 
						chainRules params.Rules
 | 
				
			||||||
	// virtual machine configuration options used to initialise the
 | 
						// virtual machine configuration options used to initialise the
 | 
				
			||||||
	// evm.
 | 
						// evm.
 | 
				
			||||||
	vmConfig Config
 | 
						vmConfig Config
 | 
				
			||||||
@@ -79,21 +100,23 @@ type EVM struct {
 | 
				
			|||||||
	abort int32
 | 
						abort int32
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewEVM retutrns a new EVM evmironment.
 | 
					// NewEVM retutrns a new EVM evmironment. The returned EVM is not thread safe
 | 
				
			||||||
 | 
					// and should only ever be used *once*.
 | 
				
			||||||
func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
 | 
					func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
 | 
				
			||||||
	evm := &EVM{
 | 
						evm := &EVM{
 | 
				
			||||||
		Context:     ctx,
 | 
							Context:     ctx,
 | 
				
			||||||
		StateDB:     statedb,
 | 
							StateDB:     statedb,
 | 
				
			||||||
		vmConfig:    vmConfig,
 | 
							vmConfig:    vmConfig,
 | 
				
			||||||
		chainConfig: chainConfig,
 | 
							chainConfig: chainConfig,
 | 
				
			||||||
 | 
							chainRules:  chainConfig.Rules(ctx.BlockNumber),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	evm.interpreter = NewInterpreter(evm, vmConfig)
 | 
						evm.interpreter = NewInterpreter(evm, vmConfig)
 | 
				
			||||||
	return evm
 | 
						return evm
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Cancel cancels any running EVM operation. This may be called concurrently and it's safe to be
 | 
					// Cancel cancels any running EVM operation. This may be called concurrently and
 | 
				
			||||||
// called multiple times.
 | 
					// it's safe to be called multiple times.
 | 
				
			||||||
func (evm *EVM) Cancel() {
 | 
					func (evm *EVM) Cancel() {
 | 
				
			||||||
	atomic.StoreInt32(&evm.abort, 1)
 | 
						atomic.StoreInt32(&evm.abort, 1)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -134,13 +157,12 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
 | 
				
			|||||||
	contract := NewContract(caller, to, value, gas)
 | 
						contract := NewContract(caller, to, value, gas)
 | 
				
			||||||
	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
 | 
						contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret, err = evm.interpreter.Run(contract, input)
 | 
						ret, err = run(evm, snapshot, contract, input)
 | 
				
			||||||
	// When an error was returned by the EVM or when setting the creation code
 | 
						// When an error was returned by the EVM or when setting the creation code
 | 
				
			||||||
	// above we revert to the snapshot and consume any gas remaining. Additionally
 | 
						// above we revert to the snapshot and consume any gas remaining. Additionally
 | 
				
			||||||
	// when we're in homestead this also counts for code storage gas errors.
 | 
						// when we're in homestead this also counts for code storage gas errors.
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		contract.UseGas(contract.Gas)
 | 
							contract.UseGas(contract.Gas)
 | 
				
			||||||
 | 
					 | 
				
			||||||
		evm.StateDB.RevertToSnapshot(snapshot)
 | 
							evm.StateDB.RevertToSnapshot(snapshot)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return ret, contract.Gas, err
 | 
						return ret, contract.Gas, err
 | 
				
			||||||
@@ -175,10 +197,9 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
 | 
				
			|||||||
	contract := NewContract(caller, to, value, gas)
 | 
						contract := NewContract(caller, to, value, gas)
 | 
				
			||||||
	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
 | 
						contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret, err = evm.interpreter.Run(contract, input)
 | 
						ret, err = run(evm, snapshot, contract, input)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		contract.UseGas(contract.Gas)
 | 
							contract.UseGas(contract.Gas)
 | 
				
			||||||
 | 
					 | 
				
			||||||
		evm.StateDB.RevertToSnapshot(snapshot)
 | 
							evm.StateDB.RevertToSnapshot(snapshot)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -210,10 +231,9 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
 | 
				
			|||||||
	contract := NewContract(caller, to, nil, gas).AsDelegate()
 | 
						contract := NewContract(caller, to, nil, gas).AsDelegate()
 | 
				
			||||||
	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
 | 
						contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret, err = evm.interpreter.Run(contract, input)
 | 
						ret, err = run(evm, snapshot, contract, input)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		contract.UseGas(contract.Gas)
 | 
							contract.UseGas(contract.Gas)
 | 
				
			||||||
 | 
					 | 
				
			||||||
		evm.StateDB.RevertToSnapshot(snapshot)
 | 
							evm.StateDB.RevertToSnapshot(snapshot)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -253,8 +273,7 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I
 | 
				
			|||||||
	contract := NewContract(caller, AccountRef(contractAddr), value, gas)
 | 
						contract := NewContract(caller, AccountRef(contractAddr), value, gas)
 | 
				
			||||||
	contract.SetCallCode(&contractAddr, crypto.Keccak256Hash(code), code)
 | 
						contract.SetCallCode(&contractAddr, crypto.Keccak256Hash(code), code)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret, err = evm.interpreter.Run(contract, nil)
 | 
						ret, err = run(evm, snapshot, contract, nil)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// check whether the max code size has been exceeded
 | 
						// check whether the max code size has been exceeded
 | 
				
			||||||
	maxCodeSizeExceeded := len(ret) > params.MaxCodeSize
 | 
						maxCodeSizeExceeded := len(ret) > params.MaxCodeSize
 | 
				
			||||||
	// if the contract creation ran successfully and no errors were returned
 | 
						// if the contract creation ran successfully and no errors were returned
 | 
				
			||||||
@@ -275,10 +294,8 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I
 | 
				
			|||||||
	// when we're in homestead this also counts for code storage gas errors.
 | 
						// when we're in homestead this also counts for code storage gas errors.
 | 
				
			||||||
	if maxCodeSizeExceeded ||
 | 
						if maxCodeSizeExceeded ||
 | 
				
			||||||
		(err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) {
 | 
							(err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) {
 | 
				
			||||||
 | 
							contract.UseGas(contract.Gas)
 | 
				
			||||||
		evm.StateDB.RevertToSnapshot(snapshot)
 | 
							evm.StateDB.RevertToSnapshot(snapshot)
 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Nothing should be returned when an error is thrown.
 | 
					 | 
				
			||||||
		return nil, contractAddr, 0, err
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// If the vm returned with an error the return value should be set to nil.
 | 
						// If the vm returned with an error the return value should be set to nil.
 | 
				
			||||||
	// This isn't consensus critical but merely to for behaviour reasons such as
 | 
						// This isn't consensus critical but merely to for behaviour reasons such as
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,7 +27,9 @@ import (
 | 
				
			|||||||
	"github.com/ethereum/go-ethereum/params"
 | 
						"github.com/ethereum/go-ethereum/params"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var bigZero = new(big.Int)
 | 
					var (
 | 
				
			||||||
 | 
						bigZero = new(big.Int)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
 | 
					func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
 | 
				
			||||||
	x, y := stack.pop(), stack.pop()
 | 
						x, y := stack.pop(), stack.pop()
 | 
				
			||||||
@@ -599,7 +601,7 @@ func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta
 | 
				
			|||||||
	contract.Gas += returnGas
 | 
						contract.Gas += returnGas
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	evm.interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize)
 | 
						evm.interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize)
 | 
				
			||||||
	return nil, nil
 | 
						return ret, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func opCallCode(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
 | 
					func opCallCode(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
 | 
				
			||||||
@@ -633,16 +635,10 @@ func opCallCode(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
 | 
				
			|||||||
	contract.Gas += returnGas
 | 
						contract.Gas += returnGas
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	evm.interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize)
 | 
						evm.interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize)
 | 
				
			||||||
	return nil, nil
 | 
						return ret, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func opDelegateCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
 | 
					func opDelegateCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
 | 
				
			||||||
	// if not homestead return an error. DELEGATECALL is not supported
 | 
					 | 
				
			||||||
	// during pre-homestead.
 | 
					 | 
				
			||||||
	if !evm.ChainConfig().IsHomestead(evm.BlockNumber) {
 | 
					 | 
				
			||||||
		return nil, fmt.Errorf("invalid opcode %x", DELEGATECALL)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	gas, to, inOffset, inSize, outOffset, outSize := stack.pop().Uint64(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
 | 
						gas, to, inOffset, inSize, outOffset, outSize := stack.pop().Uint64(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	toAddr := common.BigToAddress(to)
 | 
						toAddr := common.BigToAddress(to)
 | 
				
			||||||
@@ -658,7 +654,7 @@ func opDelegateCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, st
 | 
				
			|||||||
	contract.Gas += returnGas
 | 
						contract.Gas += returnGas
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	evm.interpreter.intPool.put(to, inOffset, inSize, outOffset, outSize)
 | 
						evm.interpreter.intPool.put(to, inOffset, inSize, outOffset, outSize)
 | 
				
			||||||
	return nil, nil
 | 
						return ret, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func opReturn(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
 | 
					func opReturn(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
 | 
				
			||||||
@@ -666,6 +662,7 @@ func opReturn(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S
 | 
				
			|||||||
	ret := memory.GetPtr(offset.Int64(), size.Int64())
 | 
						ret := memory.GetPtr(offset.Int64(), size.Int64())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	evm.interpreter.intPool.put(offset, size)
 | 
						evm.interpreter.intPool.put(offset, size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret, nil
 | 
						return ret, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,50 +45,60 @@ type Config struct {
 | 
				
			|||||||
	DisableGasMetering bool
 | 
						DisableGasMetering bool
 | 
				
			||||||
	// Enable recording of SHA3/keccak preimages
 | 
						// Enable recording of SHA3/keccak preimages
 | 
				
			||||||
	EnablePreimageRecording bool
 | 
						EnablePreimageRecording bool
 | 
				
			||||||
	// JumpTable contains the EVM instruction table. This
 | 
						// JumpTable contains the in instruction table. This
 | 
				
			||||||
	// may me left uninitialised and will be set the default
 | 
						// may me left uninitialised and will be set the default
 | 
				
			||||||
	// table.
 | 
						// table.
 | 
				
			||||||
	JumpTable [256]operation
 | 
						JumpTable [256]operation
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Interpreter is used to run Ethereum based contracts and will utilise the
 | 
					// Interpreter is used to run Ethereum based contracts and will utilise the
 | 
				
			||||||
// passed environment to query external sources for state information.
 | 
					// passed evmironment to query external sources for state information.
 | 
				
			||||||
// The Interpreter will run the byte code VM or JIT VM based on the passed
 | 
					// The Interpreter will run the byte code VM or JIT VM based on the passed
 | 
				
			||||||
// configuration.
 | 
					// configuration.
 | 
				
			||||||
type Interpreter struct {
 | 
					type Interpreter struct {
 | 
				
			||||||
	env      *EVM
 | 
						evm      *EVM
 | 
				
			||||||
	cfg      Config
 | 
						cfg      Config
 | 
				
			||||||
	gasTable params.GasTable
 | 
						gasTable params.GasTable
 | 
				
			||||||
	intPool  *intPool
 | 
						intPool  *intPool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						readonly bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewInterpreter returns a new instance of the Interpreter.
 | 
					// NewInterpreter returns a new instance of the Interpreter.
 | 
				
			||||||
func NewInterpreter(env *EVM, cfg Config) *Interpreter {
 | 
					func NewInterpreter(evm *EVM, cfg Config) *Interpreter {
 | 
				
			||||||
	// We use the STOP instruction whether to see
 | 
						// We use the STOP instruction whether to see
 | 
				
			||||||
	// the jump table was initialised. If it was not
 | 
						// the jump table was initialised. If it was not
 | 
				
			||||||
	// we'll set the default jump table.
 | 
						// we'll set the default jump table.
 | 
				
			||||||
	if !cfg.JumpTable[STOP].valid {
 | 
						if !cfg.JumpTable[STOP].valid {
 | 
				
			||||||
		cfg.JumpTable = defaultJumpTable
 | 
							switch {
 | 
				
			||||||
 | 
							case evm.ChainConfig().IsHomestead(evm.BlockNumber):
 | 
				
			||||||
 | 
								cfg.JumpTable = homesteadInstructionSet
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								cfg.JumpTable = baseInstructionSet
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &Interpreter{
 | 
						return &Interpreter{
 | 
				
			||||||
		env:      env,
 | 
							evm:      evm,
 | 
				
			||||||
		cfg:      cfg,
 | 
							cfg:      cfg,
 | 
				
			||||||
		gasTable: env.ChainConfig().GasTable(env.BlockNumber),
 | 
							gasTable: evm.ChainConfig().GasTable(evm.BlockNumber),
 | 
				
			||||||
		intPool:  newIntPool(),
 | 
							intPool:  newIntPool(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Run loops and evaluates the contract's code with the given input data
 | 
					func (in *Interpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error {
 | 
				
			||||||
func (evm *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err error) {
 | 
						return nil
 | 
				
			||||||
	evm.env.depth++
 | 
					}
 | 
				
			||||||
	defer func() { evm.env.depth-- }()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if contract.CodeAddr != nil {
 | 
					// Run loops and evaluates the contract's code with the given input data and returns
 | 
				
			||||||
		if p := PrecompiledContracts[*contract.CodeAddr]; p != nil {
 | 
					// the return byte-slice and an error if one occured.
 | 
				
			||||||
			return RunPrecompiledContract(p, input, contract)
 | 
					//
 | 
				
			||||||
		}
 | 
					// It's important to note that any errors returned by the interpreter should be
 | 
				
			||||||
	}
 | 
					// considered a revert-and-consume-all-gas operation. No error specific checks
 | 
				
			||||||
 | 
					// should be handled to reduce complexity and errors further down the in.
 | 
				
			||||||
 | 
					func (in *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret []byte, err error) {
 | 
				
			||||||
 | 
						in.evm.depth++
 | 
				
			||||||
 | 
						defer func() { in.evm.depth-- }()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Don't bother with the execution if there's no code.
 | 
						// Don't bother with the execution if there's no code.
 | 
				
			||||||
	if len(contract.Code) == 0 {
 | 
						if len(contract.Code) == 0 {
 | 
				
			||||||
@@ -105,7 +115,8 @@ func (evm *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err e
 | 
				
			|||||||
		mem   = NewMemory() // bound memory
 | 
							mem   = NewMemory() // bound memory
 | 
				
			||||||
		stack = newstack()  // local stack
 | 
							stack = newstack()  // local stack
 | 
				
			||||||
		// For optimisation reason we're using uint64 as the program counter.
 | 
							// For optimisation reason we're using uint64 as the program counter.
 | 
				
			||||||
		// It's theoretically possible to go above 2^64. The YP defines the PC to be uint256. Practically much less so feasible.
 | 
							// It's theoretically possible to go above 2^64. The YP defines the PC
 | 
				
			||||||
 | 
							// to be uint256. Practically much less so feasible.
 | 
				
			||||||
		pc   = uint64(0) // program counter
 | 
							pc   = uint64(0) // program counter
 | 
				
			||||||
		cost uint64
 | 
							cost uint64
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
@@ -113,27 +124,30 @@ func (evm *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err e
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
 | 
						// User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
 | 
				
			||||||
	defer func() {
 | 
						defer func() {
 | 
				
			||||||
		if err != nil && evm.cfg.Debug {
 | 
							if err != nil && in.cfg.Debug {
 | 
				
			||||||
			// XXX For debugging
 | 
								// XXX For debugging
 | 
				
			||||||
			//fmt.Printf("%04d: %8v    cost = %-8d stack = %-8d ERR = %v\n", pc, op, cost, stack.len(), err)
 | 
								//fmt.Printf("%04d: %8v    cost = %-8d stack = %-8d ERR = %v\n", pc, op, cost, stack.len(), err)
 | 
				
			||||||
			evm.cfg.Tracer.CaptureState(evm.env, pc, op, contract.Gas, cost, mem, stack, contract, evm.env.depth, err)
 | 
								in.cfg.Tracer.CaptureState(in.evm, pc, op, contract.Gas, cost, mem, stack, contract, in.evm.depth, err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Debug("EVM running contract", "hash", codehash[:])
 | 
						log.Debug("in running contract", "hash", codehash[:])
 | 
				
			||||||
	tstart := time.Now()
 | 
						tstart := time.Now()
 | 
				
			||||||
	defer log.Debug("EVM finished running contract", "hash", codehash[:], "elapsed", time.Since(tstart))
 | 
						defer log.Debug("in finished running contract", "hash", codehash[:], "elapsed", time.Since(tstart))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The Interpreter main run loop (contextual). This loop runs until either an
 | 
						// The Interpreter main run loop (contextual). This loop runs until either an
 | 
				
			||||||
	// explicit STOP, RETURN or SELFDESTRUCT is executed, an error occurred during
 | 
						// explicit STOP, RETURN or SELFDESTRUCT is executed, an error occurred during
 | 
				
			||||||
	// the execution of one of the operations or until the evm.done is set by
 | 
						// the execution of one of the operations or until the in.done is set by
 | 
				
			||||||
	// the parent context.Context.
 | 
						// the parent context.Context.
 | 
				
			||||||
	for atomic.LoadInt32(&evm.env.abort) == 0 {
 | 
						for atomic.LoadInt32(&in.evm.abort) == 0 {
 | 
				
			||||||
		// Get the memory location of pc
 | 
							// Get the memory location of pc
 | 
				
			||||||
		op = contract.GetOp(pc)
 | 
							op = contract.GetOp(pc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// get the operation from the jump table matching the opcode
 | 
							// get the operation from the jump table matching the opcode
 | 
				
			||||||
		operation := evm.cfg.JumpTable[op]
 | 
							operation := in.cfg.JumpTable[op]
 | 
				
			||||||
 | 
							if err := in.enforceRestrictions(op, operation, stack); err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// if the op is invalid abort the process and return an error
 | 
							// if the op is invalid abort the process and return an error
 | 
				
			||||||
		if !operation.valid {
 | 
							if !operation.valid {
 | 
				
			||||||
@@ -161,10 +175,10 @@ func (evm *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err e
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !evm.cfg.DisableGasMetering {
 | 
							if !in.cfg.DisableGasMetering {
 | 
				
			||||||
			// consume the gas and return an error if not enough gas is available.
 | 
								// consume the gas and return an error if not enough gas is available.
 | 
				
			||||||
			// cost is explicitly set so that the capture state defer method cas get the proper cost
 | 
								// cost is explicitly set so that the capture state defer method cas get the proper cost
 | 
				
			||||||
			cost, err = operation.gasCost(evm.gasTable, evm.env, contract, stack, mem, memorySize)
 | 
								cost, err = operation.gasCost(in.gasTable, in.evm, contract, stack, mem, memorySize)
 | 
				
			||||||
			if err != nil || !contract.UseGas(cost) {
 | 
								if err != nil || !contract.UseGas(cost) {
 | 
				
			||||||
				return nil, ErrOutOfGas
 | 
									return nil, ErrOutOfGas
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -173,19 +187,20 @@ func (evm *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err e
 | 
				
			|||||||
			mem.Resize(memorySize)
 | 
								mem.Resize(memorySize)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if evm.cfg.Debug {
 | 
							if in.cfg.Debug {
 | 
				
			||||||
			evm.cfg.Tracer.CaptureState(evm.env, pc, op, contract.Gas, cost, mem, stack, contract, evm.env.depth, err)
 | 
								in.cfg.Tracer.CaptureState(in.evm, pc, op, contract.Gas, cost, mem, stack, contract, in.evm.depth, err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// XXX For debugging
 | 
							// XXX For debugging
 | 
				
			||||||
		//fmt.Printf("%04d: %8v    cost = %-8d stack = %-8d\n", pc, op, cost, stack.len())
 | 
							//fmt.Printf("%04d: %8v    cost = %-8d stack = %-8d\n", pc, op, cost, stack.len())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// execute the operation
 | 
							// execute the operation
 | 
				
			||||||
		res, err := operation.execute(&pc, evm.env, contract, mem, stack)
 | 
							res, err := operation.execute(&pc, in.evm, contract, mem, stack)
 | 
				
			||||||
		// verifyPool is a build flag. Pool verification makes sure the integrity
 | 
							// verifyPool is a build flag. Pool verification makes sure the integrity
 | 
				
			||||||
		// of the integer pool by comparing values to a default value.
 | 
							// of the integer pool by comparing values to a default value.
 | 
				
			||||||
		if verifyPool {
 | 
							if verifyPool {
 | 
				
			||||||
			verifyIntegerPool(evm.intPool)
 | 
								verifyIntegerPool(in.intPool)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch {
 | 
							switch {
 | 
				
			||||||
		case err != nil:
 | 
							case err != nil:
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
@@ -194,6 +209,11 @@ func (evm *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err e
 | 
				
			|||||||
		case !operation.jumps:
 | 
							case !operation.jumps:
 | 
				
			||||||
			pc++
 | 
								pc++
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							// if the operation returned a value make sure that is also set
 | 
				
			||||||
 | 
							// the last return data.
 | 
				
			||||||
 | 
							if res != nil {
 | 
				
			||||||
 | 
								mem.lastReturn = ret
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil, nil
 | 
						return nil, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,13 +47,32 @@ type operation struct {
 | 
				
			|||||||
	// jumps indicates whether operation made a jump. This prevents the program
 | 
						// jumps indicates whether operation made a jump. This prevents the program
 | 
				
			||||||
	// counter from further incrementing.
 | 
						// counter from further incrementing.
 | 
				
			||||||
	jumps bool
 | 
						jumps bool
 | 
				
			||||||
 | 
						// writes determines whether this a state modifying operation
 | 
				
			||||||
 | 
						writes bool
 | 
				
			||||||
	// valid is used to check whether the retrieved operation is valid and known
 | 
						// valid is used to check whether the retrieved operation is valid and known
 | 
				
			||||||
	valid bool
 | 
						valid bool
 | 
				
			||||||
 | 
						// reverts determined whether the operation reverts state
 | 
				
			||||||
 | 
						reverts bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var defaultJumpTable = NewJumpTable()
 | 
					var (
 | 
				
			||||||
 | 
						baseInstructionSet      = NewBaseInstructionSet()
 | 
				
			||||||
 | 
						homesteadInstructionSet = NewHomesteadInstructionSet()
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewJumpTable() [256]operation {
 | 
					func NewHomesteadInstructionSet() [256]operation {
 | 
				
			||||||
 | 
						instructionSet := NewBaseInstructionSet()
 | 
				
			||||||
 | 
						instructionSet[DELEGATECALL] = operation{
 | 
				
			||||||
 | 
							execute:       opDelegateCall,
 | 
				
			||||||
 | 
							gasCost:       gasDelegateCall,
 | 
				
			||||||
 | 
							validateStack: makeStackFunc(6, 1),
 | 
				
			||||||
 | 
							memorySize:    memoryDelegateCall,
 | 
				
			||||||
 | 
							valid:         true,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return instructionSet
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewBaseInstructionSet() [256]operation {
 | 
				
			||||||
	return [256]operation{
 | 
						return [256]operation{
 | 
				
			||||||
		STOP: {
 | 
							STOP: {
 | 
				
			||||||
			execute:       opStop,
 | 
								execute:       opStop,
 | 
				
			||||||
@@ -357,6 +376,7 @@ func NewJumpTable() [256]operation {
 | 
				
			|||||||
			gasCost:       gasSStore,
 | 
								gasCost:       gasSStore,
 | 
				
			||||||
			validateStack: makeStackFunc(2, 0),
 | 
								validateStack: makeStackFunc(2, 0),
 | 
				
			||||||
			valid:         true,
 | 
								valid:         true,
 | 
				
			||||||
 | 
								writes:        true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		JUMP: {
 | 
							JUMP: {
 | 
				
			||||||
			execute:       opJump,
 | 
								execute:       opJump,
 | 
				
			||||||
@@ -821,6 +841,7 @@ func NewJumpTable() [256]operation {
 | 
				
			|||||||
			validateStack: makeStackFunc(3, 1),
 | 
								validateStack: makeStackFunc(3, 1),
 | 
				
			||||||
			memorySize:    memoryCreate,
 | 
								memorySize:    memoryCreate,
 | 
				
			||||||
			valid:         true,
 | 
								valid:         true,
 | 
				
			||||||
 | 
								writes:        true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		CALL: {
 | 
							CALL: {
 | 
				
			||||||
			execute:       opCall,
 | 
								execute:       opCall,
 | 
				
			||||||
@@ -844,19 +865,13 @@ func NewJumpTable() [256]operation {
 | 
				
			|||||||
			halts:         true,
 | 
								halts:         true,
 | 
				
			||||||
			valid:         true,
 | 
								valid:         true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		DELEGATECALL: {
 | 
					 | 
				
			||||||
			execute:       opDelegateCall,
 | 
					 | 
				
			||||||
			gasCost:       gasDelegateCall,
 | 
					 | 
				
			||||||
			validateStack: makeStackFunc(6, 1),
 | 
					 | 
				
			||||||
			memorySize:    memoryDelegateCall,
 | 
					 | 
				
			||||||
			valid:         true,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		SELFDESTRUCT: {
 | 
							SELFDESTRUCT: {
 | 
				
			||||||
			execute:       opSuicide,
 | 
								execute:       opSuicide,
 | 
				
			||||||
			gasCost:       gasSuicide,
 | 
								gasCost:       gasSuicide,
 | 
				
			||||||
			validateStack: makeStackFunc(1, 0),
 | 
								validateStack: makeStackFunc(1, 0),
 | 
				
			||||||
			halts:         true,
 | 
								halts:         true,
 | 
				
			||||||
			valid:         true,
 | 
								valid:         true,
 | 
				
			||||||
 | 
								writes:        true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,7 @@ import "fmt"
 | 
				
			|||||||
type Memory struct {
 | 
					type Memory struct {
 | 
				
			||||||
	store       []byte
 | 
						store       []byte
 | 
				
			||||||
	lastGasCost uint64
 | 
						lastGasCost uint64
 | 
				
			||||||
 | 
						lastReturn  []byte
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewMemory() *Memory {
 | 
					func NewMemory() *Memory {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										428
									
								
								crypto/bn256/bn256.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										428
									
								
								crypto/bn256/bn256.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,428 @@
 | 
				
			|||||||
 | 
					// Copyright 2012 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Package bn256 implements a particular bilinear group at the 128-bit security level.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Bilinear groups are the basis of many of the new cryptographic protocols
 | 
				
			||||||
 | 
					// that have been proposed over the past decade. They consist of a triplet of
 | 
				
			||||||
 | 
					// groups (G₁, G₂ and GT) such that there exists a function e(g₁ˣ,g₂ʸ)=gTˣʸ
 | 
				
			||||||
 | 
					// (where gₓ is a generator of the respective group). That function is called
 | 
				
			||||||
 | 
					// a pairing function.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This package specifically implements the Optimal Ate pairing over a 256-bit
 | 
				
			||||||
 | 
					// Barreto-Naehrig curve as described in
 | 
				
			||||||
 | 
					// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible
 | 
				
			||||||
 | 
					// with the implementation described in that paper.
 | 
				
			||||||
 | 
					package bn256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/rand"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// BUG(agl): this implementation is not constant time.
 | 
				
			||||||
 | 
					// TODO(agl): keep GF(p²) elements in Mongomery form.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// G1 is an abstract cyclic group. The zero value is suitable for use as the
 | 
				
			||||||
 | 
					// output of an operation, but cannot be used as an input.
 | 
				
			||||||
 | 
					type G1 struct {
 | 
				
			||||||
 | 
						p *curvePoint
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RandomG1 returns x and g₁ˣ where x is a random, non-zero number read from r.
 | 
				
			||||||
 | 
					func RandomG1(r io.Reader) (*big.Int, *G1, error) {
 | 
				
			||||||
 | 
						var k *big.Int
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							k, err = rand.Int(r, Order)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if k.Sign() > 0 {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return k, new(G1).ScalarBaseMult(k), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *G1) String() string {
 | 
				
			||||||
 | 
						return "bn256.G1" + g.p.String()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CurvePoints returns p's curve points in big integer
 | 
				
			||||||
 | 
					func (e *G1) CurvePoints() (*big.Int, *big.Int, *big.Int, *big.Int) {
 | 
				
			||||||
 | 
						return e.p.x, e.p.y, e.p.z, e.p.t
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ScalarBaseMult sets e to g*k where g is the generator of the group and
 | 
				
			||||||
 | 
					// then returns e.
 | 
				
			||||||
 | 
					func (e *G1) ScalarBaseMult(k *big.Int) *G1 {
 | 
				
			||||||
 | 
						if e.p == nil {
 | 
				
			||||||
 | 
							e.p = newCurvePoint(nil)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						e.p.Mul(curveGen, k, new(bnPool))
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ScalarMult sets e to a*k and then returns e.
 | 
				
			||||||
 | 
					func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 {
 | 
				
			||||||
 | 
						if e.p == nil {
 | 
				
			||||||
 | 
							e.p = newCurvePoint(nil)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						e.p.Mul(a.p, k, new(bnPool))
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Add sets e to a+b and then returns e.
 | 
				
			||||||
 | 
					// BUG(agl): this function is not complete: a==b fails.
 | 
				
			||||||
 | 
					func (e *G1) Add(a, b *G1) *G1 {
 | 
				
			||||||
 | 
						if e.p == nil {
 | 
				
			||||||
 | 
							e.p = newCurvePoint(nil)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						e.p.Add(a.p, b.p, new(bnPool))
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Neg sets e to -a and then returns e.
 | 
				
			||||||
 | 
					func (e *G1) Neg(a *G1) *G1 {
 | 
				
			||||||
 | 
						if e.p == nil {
 | 
				
			||||||
 | 
							e.p = newCurvePoint(nil)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						e.p.Negative(a.p)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Marshal converts n to a byte slice.
 | 
				
			||||||
 | 
					func (n *G1) Marshal() []byte {
 | 
				
			||||||
 | 
						n.p.MakeAffine(nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xBytes := new(big.Int).Mod(n.p.x, P).Bytes()
 | 
				
			||||||
 | 
						yBytes := new(big.Int).Mod(n.p.y, P).Bytes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Each value is a 256-bit number.
 | 
				
			||||||
 | 
						const numBytes = 256 / 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret := make([]byte, numBytes*2)
 | 
				
			||||||
 | 
						copy(ret[1*numBytes-len(xBytes):], xBytes)
 | 
				
			||||||
 | 
						copy(ret[2*numBytes-len(yBytes):], yBytes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Unmarshal sets e to the result of converting the output of Marshal back into
 | 
				
			||||||
 | 
					// a group element and then returns e.
 | 
				
			||||||
 | 
					func (e *G1) Unmarshal(m []byte) (*G1, bool) {
 | 
				
			||||||
 | 
						// Each value is a 256-bit number.
 | 
				
			||||||
 | 
						const numBytes = 256 / 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(m) != 2*numBytes {
 | 
				
			||||||
 | 
							return nil, false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if e.p == nil {
 | 
				
			||||||
 | 
							e.p = newCurvePoint(nil)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e.p.x.SetBytes(m[0*numBytes : 1*numBytes])
 | 
				
			||||||
 | 
						e.p.y.SetBytes(m[1*numBytes : 2*numBytes])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if e.p.x.Sign() == 0 && e.p.y.Sign() == 0 {
 | 
				
			||||||
 | 
							// This is the point at infinity.
 | 
				
			||||||
 | 
							e.p.y.SetInt64(1)
 | 
				
			||||||
 | 
							e.p.z.SetInt64(0)
 | 
				
			||||||
 | 
							e.p.t.SetInt64(0)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							e.p.z.SetInt64(1)
 | 
				
			||||||
 | 
							e.p.t.SetInt64(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !e.p.IsOnCurve() {
 | 
				
			||||||
 | 
								return nil, false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return e, true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// G2 is an abstract cyclic group. The zero value is suitable for use as the
 | 
				
			||||||
 | 
					// output of an operation, but cannot be used as an input.
 | 
				
			||||||
 | 
					type G2 struct {
 | 
				
			||||||
 | 
						p *twistPoint
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RandomG1 returns x and g₂ˣ where x is a random, non-zero number read from r.
 | 
				
			||||||
 | 
					func RandomG2(r io.Reader) (*big.Int, *G2, error) {
 | 
				
			||||||
 | 
						var k *big.Int
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							k, err = rand.Int(r, Order)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if k.Sign() > 0 {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return k, new(G2).ScalarBaseMult(k), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *G2) String() string {
 | 
				
			||||||
 | 
						return "bn256.G2" + g.p.String()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CurvePoints returns the curve points of p which includes the real
 | 
				
			||||||
 | 
					// and imaginary parts of the curve point.
 | 
				
			||||||
 | 
					func (e *G2) CurvePoints() (*gfP2, *gfP2, *gfP2, *gfP2) {
 | 
				
			||||||
 | 
						return e.p.x, e.p.y, e.p.z, e.p.t
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ScalarBaseMult sets e to g*k where g is the generator of the group and
 | 
				
			||||||
 | 
					// then returns out.
 | 
				
			||||||
 | 
					func (e *G2) ScalarBaseMult(k *big.Int) *G2 {
 | 
				
			||||||
 | 
						if e.p == nil {
 | 
				
			||||||
 | 
							e.p = newTwistPoint(nil)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						e.p.Mul(twistGen, k, new(bnPool))
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ScalarMult sets e to a*k and then returns e.
 | 
				
			||||||
 | 
					func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 {
 | 
				
			||||||
 | 
						if e.p == nil {
 | 
				
			||||||
 | 
							e.p = newTwistPoint(nil)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						e.p.Mul(a.p, k, new(bnPool))
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Add sets e to a+b and then returns e.
 | 
				
			||||||
 | 
					// BUG(agl): this function is not complete: a==b fails.
 | 
				
			||||||
 | 
					func (e *G2) Add(a, b *G2) *G2 {
 | 
				
			||||||
 | 
						if e.p == nil {
 | 
				
			||||||
 | 
							e.p = newTwistPoint(nil)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						e.p.Add(a.p, b.p, new(bnPool))
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Marshal converts n into a byte slice.
 | 
				
			||||||
 | 
					func (n *G2) Marshal() []byte {
 | 
				
			||||||
 | 
						n.p.MakeAffine(nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xxBytes := new(big.Int).Mod(n.p.x.x, P).Bytes()
 | 
				
			||||||
 | 
						xyBytes := new(big.Int).Mod(n.p.x.y, P).Bytes()
 | 
				
			||||||
 | 
						yxBytes := new(big.Int).Mod(n.p.y.x, P).Bytes()
 | 
				
			||||||
 | 
						yyBytes := new(big.Int).Mod(n.p.y.y, P).Bytes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Each value is a 256-bit number.
 | 
				
			||||||
 | 
						const numBytes = 256 / 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret := make([]byte, numBytes*4)
 | 
				
			||||||
 | 
						copy(ret[1*numBytes-len(xxBytes):], xxBytes)
 | 
				
			||||||
 | 
						copy(ret[2*numBytes-len(xyBytes):], xyBytes)
 | 
				
			||||||
 | 
						copy(ret[3*numBytes-len(yxBytes):], yxBytes)
 | 
				
			||||||
 | 
						copy(ret[4*numBytes-len(yyBytes):], yyBytes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Unmarshal sets e to the result of converting the output of Marshal back into
 | 
				
			||||||
 | 
					// a group element and then returns e.
 | 
				
			||||||
 | 
					func (e *G2) Unmarshal(m []byte) (*G2, bool) {
 | 
				
			||||||
 | 
						// Each value is a 256-bit number.
 | 
				
			||||||
 | 
						const numBytes = 256 / 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(m) != 4*numBytes {
 | 
				
			||||||
 | 
							return nil, false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if e.p == nil {
 | 
				
			||||||
 | 
							e.p = newTwistPoint(nil)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e.p.x.x.SetBytes(m[0*numBytes : 1*numBytes])
 | 
				
			||||||
 | 
						e.p.x.y.SetBytes(m[1*numBytes : 2*numBytes])
 | 
				
			||||||
 | 
						e.p.y.x.SetBytes(m[2*numBytes : 3*numBytes])
 | 
				
			||||||
 | 
						e.p.y.y.SetBytes(m[3*numBytes : 4*numBytes])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if e.p.x.x.Sign() == 0 &&
 | 
				
			||||||
 | 
							e.p.x.y.Sign() == 0 &&
 | 
				
			||||||
 | 
							e.p.y.x.Sign() == 0 &&
 | 
				
			||||||
 | 
							e.p.y.y.Sign() == 0 {
 | 
				
			||||||
 | 
							// This is the point at infinity.
 | 
				
			||||||
 | 
							e.p.y.SetOne()
 | 
				
			||||||
 | 
							e.p.z.SetZero()
 | 
				
			||||||
 | 
							e.p.t.SetZero()
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							e.p.z.SetOne()
 | 
				
			||||||
 | 
							e.p.t.SetOne()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !e.p.IsOnCurve() {
 | 
				
			||||||
 | 
								return nil, false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return e, true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GT is an abstract cyclic group. The zero value is suitable for use as the
 | 
				
			||||||
 | 
					// output of an operation, but cannot be used as an input.
 | 
				
			||||||
 | 
					type GT struct {
 | 
				
			||||||
 | 
						p *gfP12
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *GT) String() string {
 | 
				
			||||||
 | 
						return "bn256.GT" + g.p.String()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ScalarMult sets e to a*k and then returns e.
 | 
				
			||||||
 | 
					func (e *GT) ScalarMult(a *GT, k *big.Int) *GT {
 | 
				
			||||||
 | 
						if e.p == nil {
 | 
				
			||||||
 | 
							e.p = newGFp12(nil)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						e.p.Exp(a.p, k, new(bnPool))
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Add sets e to a+b and then returns e.
 | 
				
			||||||
 | 
					func (e *GT) Add(a, b *GT) *GT {
 | 
				
			||||||
 | 
						if e.p == nil {
 | 
				
			||||||
 | 
							e.p = newGFp12(nil)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						e.p.Mul(a.p, b.p, new(bnPool))
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Neg sets e to -a and then returns e.
 | 
				
			||||||
 | 
					func (e *GT) Neg(a *GT) *GT {
 | 
				
			||||||
 | 
						if e.p == nil {
 | 
				
			||||||
 | 
							e.p = newGFp12(nil)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						e.p.Invert(a.p, new(bnPool))
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Marshal converts n into a byte slice.
 | 
				
			||||||
 | 
					func (n *GT) Marshal() []byte {
 | 
				
			||||||
 | 
						n.p.Minimal()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xxxBytes := n.p.x.x.x.Bytes()
 | 
				
			||||||
 | 
						xxyBytes := n.p.x.x.y.Bytes()
 | 
				
			||||||
 | 
						xyxBytes := n.p.x.y.x.Bytes()
 | 
				
			||||||
 | 
						xyyBytes := n.p.x.y.y.Bytes()
 | 
				
			||||||
 | 
						xzxBytes := n.p.x.z.x.Bytes()
 | 
				
			||||||
 | 
						xzyBytes := n.p.x.z.y.Bytes()
 | 
				
			||||||
 | 
						yxxBytes := n.p.y.x.x.Bytes()
 | 
				
			||||||
 | 
						yxyBytes := n.p.y.x.y.Bytes()
 | 
				
			||||||
 | 
						yyxBytes := n.p.y.y.x.Bytes()
 | 
				
			||||||
 | 
						yyyBytes := n.p.y.y.y.Bytes()
 | 
				
			||||||
 | 
						yzxBytes := n.p.y.z.x.Bytes()
 | 
				
			||||||
 | 
						yzyBytes := n.p.y.z.y.Bytes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Each value is a 256-bit number.
 | 
				
			||||||
 | 
						const numBytes = 256 / 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret := make([]byte, numBytes*12)
 | 
				
			||||||
 | 
						copy(ret[1*numBytes-len(xxxBytes):], xxxBytes)
 | 
				
			||||||
 | 
						copy(ret[2*numBytes-len(xxyBytes):], xxyBytes)
 | 
				
			||||||
 | 
						copy(ret[3*numBytes-len(xyxBytes):], xyxBytes)
 | 
				
			||||||
 | 
						copy(ret[4*numBytes-len(xyyBytes):], xyyBytes)
 | 
				
			||||||
 | 
						copy(ret[5*numBytes-len(xzxBytes):], xzxBytes)
 | 
				
			||||||
 | 
						copy(ret[6*numBytes-len(xzyBytes):], xzyBytes)
 | 
				
			||||||
 | 
						copy(ret[7*numBytes-len(yxxBytes):], yxxBytes)
 | 
				
			||||||
 | 
						copy(ret[8*numBytes-len(yxyBytes):], yxyBytes)
 | 
				
			||||||
 | 
						copy(ret[9*numBytes-len(yyxBytes):], yyxBytes)
 | 
				
			||||||
 | 
						copy(ret[10*numBytes-len(yyyBytes):], yyyBytes)
 | 
				
			||||||
 | 
						copy(ret[11*numBytes-len(yzxBytes):], yzxBytes)
 | 
				
			||||||
 | 
						copy(ret[12*numBytes-len(yzyBytes):], yzyBytes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Unmarshal sets e to the result of converting the output of Marshal back into
 | 
				
			||||||
 | 
					// a group element and then returns e.
 | 
				
			||||||
 | 
					func (e *GT) Unmarshal(m []byte) (*GT, bool) {
 | 
				
			||||||
 | 
						// Each value is a 256-bit number.
 | 
				
			||||||
 | 
						const numBytes = 256 / 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(m) != 12*numBytes {
 | 
				
			||||||
 | 
							return nil, false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if e.p == nil {
 | 
				
			||||||
 | 
							e.p = newGFp12(nil)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e.p.x.x.x.SetBytes(m[0*numBytes : 1*numBytes])
 | 
				
			||||||
 | 
						e.p.x.x.y.SetBytes(m[1*numBytes : 2*numBytes])
 | 
				
			||||||
 | 
						e.p.x.y.x.SetBytes(m[2*numBytes : 3*numBytes])
 | 
				
			||||||
 | 
						e.p.x.y.y.SetBytes(m[3*numBytes : 4*numBytes])
 | 
				
			||||||
 | 
						e.p.x.z.x.SetBytes(m[4*numBytes : 5*numBytes])
 | 
				
			||||||
 | 
						e.p.x.z.y.SetBytes(m[5*numBytes : 6*numBytes])
 | 
				
			||||||
 | 
						e.p.y.x.x.SetBytes(m[6*numBytes : 7*numBytes])
 | 
				
			||||||
 | 
						e.p.y.x.y.SetBytes(m[7*numBytes : 8*numBytes])
 | 
				
			||||||
 | 
						e.p.y.y.x.SetBytes(m[8*numBytes : 9*numBytes])
 | 
				
			||||||
 | 
						e.p.y.y.y.SetBytes(m[9*numBytes : 10*numBytes])
 | 
				
			||||||
 | 
						e.p.y.z.x.SetBytes(m[10*numBytes : 11*numBytes])
 | 
				
			||||||
 | 
						e.p.y.z.y.SetBytes(m[11*numBytes : 12*numBytes])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return e, true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Pair calculates an Optimal Ate pairing.
 | 
				
			||||||
 | 
					func Pair(g1 *G1, g2 *G2) *GT {
 | 
				
			||||||
 | 
						return >{optimalAte(g2.p, g1.p, new(bnPool))}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func PairingCheck(a []*G1, b []*G2) bool {
 | 
				
			||||||
 | 
						pool := new(bnPool)
 | 
				
			||||||
 | 
						e := newGFp12(pool)
 | 
				
			||||||
 | 
						e.SetOne()
 | 
				
			||||||
 | 
						for i := 0; i < len(a); i++ {
 | 
				
			||||||
 | 
							new_e := miller(b[i].p, a[i].p, pool)
 | 
				
			||||||
 | 
							e.Mul(e, new_e, pool)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ret := finalExponentiation(e, pool)
 | 
				
			||||||
 | 
						e.Put(pool)
 | 
				
			||||||
 | 
						return ret.IsOne()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// bnPool implements a tiny cache of *big.Int objects that's used to reduce the
 | 
				
			||||||
 | 
					// number of allocations made during processing.
 | 
				
			||||||
 | 
					type bnPool struct {
 | 
				
			||||||
 | 
						bns   []*big.Int
 | 
				
			||||||
 | 
						count int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (pool *bnPool) Get() *big.Int {
 | 
				
			||||||
 | 
						if pool == nil {
 | 
				
			||||||
 | 
							return new(big.Int)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pool.count++
 | 
				
			||||||
 | 
						l := len(pool.bns)
 | 
				
			||||||
 | 
						if l == 0 {
 | 
				
			||||||
 | 
							return new(big.Int)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bn := pool.bns[l-1]
 | 
				
			||||||
 | 
						pool.bns = pool.bns[:l-1]
 | 
				
			||||||
 | 
						return bn
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (pool *bnPool) Put(bn *big.Int) {
 | 
				
			||||||
 | 
						if pool == nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pool.bns = append(pool.bns, bn)
 | 
				
			||||||
 | 
						pool.count--
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (pool *bnPool) Count() int {
 | 
				
			||||||
 | 
						return pool.count
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										304
									
								
								crypto/bn256/bn256_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										304
									
								
								crypto/bn256/bn256_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,304 @@
 | 
				
			|||||||
 | 
					// Copyright 2012 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package bn256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"crypto/rand"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestGFp2Invert(t *testing.T) {
 | 
				
			||||||
 | 
						pool := new(bnPool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						a := newGFp2(pool)
 | 
				
			||||||
 | 
						a.x.SetString("23423492374", 10)
 | 
				
			||||||
 | 
						a.y.SetString("12934872398472394827398470", 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inv := newGFp2(pool)
 | 
				
			||||||
 | 
						inv.Invert(a, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						b := newGFp2(pool).Mul(inv, a, pool)
 | 
				
			||||||
 | 
						if b.x.Int64() != 0 || b.y.Int64() != 1 {
 | 
				
			||||||
 | 
							t.Fatalf("bad result for a^-1*a: %s %s", b.x, b.y)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						a.Put(pool)
 | 
				
			||||||
 | 
						b.Put(pool)
 | 
				
			||||||
 | 
						inv.Put(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c := pool.Count(); c > 0 {
 | 
				
			||||||
 | 
							t.Errorf("Pool count non-zero: %d\n", c)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func isZero(n *big.Int) bool {
 | 
				
			||||||
 | 
						return new(big.Int).Mod(n, P).Int64() == 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func isOne(n *big.Int) bool {
 | 
				
			||||||
 | 
						return new(big.Int).Mod(n, P).Int64() == 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestGFp6Invert(t *testing.T) {
 | 
				
			||||||
 | 
						pool := new(bnPool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						a := newGFp6(pool)
 | 
				
			||||||
 | 
						a.x.x.SetString("239487238491", 10)
 | 
				
			||||||
 | 
						a.x.y.SetString("2356249827341", 10)
 | 
				
			||||||
 | 
						a.y.x.SetString("082659782", 10)
 | 
				
			||||||
 | 
						a.y.y.SetString("182703523765", 10)
 | 
				
			||||||
 | 
						a.z.x.SetString("978236549263", 10)
 | 
				
			||||||
 | 
						a.z.y.SetString("64893242", 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inv := newGFp6(pool)
 | 
				
			||||||
 | 
						inv.Invert(a, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						b := newGFp6(pool).Mul(inv, a, pool)
 | 
				
			||||||
 | 
						if !isZero(b.x.x) ||
 | 
				
			||||||
 | 
							!isZero(b.x.y) ||
 | 
				
			||||||
 | 
							!isZero(b.y.x) ||
 | 
				
			||||||
 | 
							!isZero(b.y.y) ||
 | 
				
			||||||
 | 
							!isZero(b.z.x) ||
 | 
				
			||||||
 | 
							!isOne(b.z.y) {
 | 
				
			||||||
 | 
							t.Fatalf("bad result for a^-1*a: %s", b)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						a.Put(pool)
 | 
				
			||||||
 | 
						b.Put(pool)
 | 
				
			||||||
 | 
						inv.Put(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c := pool.Count(); c > 0 {
 | 
				
			||||||
 | 
							t.Errorf("Pool count non-zero: %d\n", c)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestGFp12Invert(t *testing.T) {
 | 
				
			||||||
 | 
						pool := new(bnPool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						a := newGFp12(pool)
 | 
				
			||||||
 | 
						a.x.x.x.SetString("239846234862342323958623", 10)
 | 
				
			||||||
 | 
						a.x.x.y.SetString("2359862352529835623", 10)
 | 
				
			||||||
 | 
						a.x.y.x.SetString("928836523", 10)
 | 
				
			||||||
 | 
						a.x.y.y.SetString("9856234", 10)
 | 
				
			||||||
 | 
						a.x.z.x.SetString("235635286", 10)
 | 
				
			||||||
 | 
						a.x.z.y.SetString("5628392833", 10)
 | 
				
			||||||
 | 
						a.y.x.x.SetString("252936598265329856238956532167968", 10)
 | 
				
			||||||
 | 
						a.y.x.y.SetString("23596239865236954178968", 10)
 | 
				
			||||||
 | 
						a.y.y.x.SetString("95421692834", 10)
 | 
				
			||||||
 | 
						a.y.y.y.SetString("236548", 10)
 | 
				
			||||||
 | 
						a.y.z.x.SetString("924523", 10)
 | 
				
			||||||
 | 
						a.y.z.y.SetString("12954623", 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inv := newGFp12(pool)
 | 
				
			||||||
 | 
						inv.Invert(a, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						b := newGFp12(pool).Mul(inv, a, pool)
 | 
				
			||||||
 | 
						if !isZero(b.x.x.x) ||
 | 
				
			||||||
 | 
							!isZero(b.x.x.y) ||
 | 
				
			||||||
 | 
							!isZero(b.x.y.x) ||
 | 
				
			||||||
 | 
							!isZero(b.x.y.y) ||
 | 
				
			||||||
 | 
							!isZero(b.x.z.x) ||
 | 
				
			||||||
 | 
							!isZero(b.x.z.y) ||
 | 
				
			||||||
 | 
							!isZero(b.y.x.x) ||
 | 
				
			||||||
 | 
							!isZero(b.y.x.y) ||
 | 
				
			||||||
 | 
							!isZero(b.y.y.x) ||
 | 
				
			||||||
 | 
							!isZero(b.y.y.y) ||
 | 
				
			||||||
 | 
							!isZero(b.y.z.x) ||
 | 
				
			||||||
 | 
							!isOne(b.y.z.y) {
 | 
				
			||||||
 | 
							t.Fatalf("bad result for a^-1*a: %s", b)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						a.Put(pool)
 | 
				
			||||||
 | 
						b.Put(pool)
 | 
				
			||||||
 | 
						inv.Put(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c := pool.Count(); c > 0 {
 | 
				
			||||||
 | 
							t.Errorf("Pool count non-zero: %d\n", c)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestCurveImpl(t *testing.T) {
 | 
				
			||||||
 | 
						pool := new(bnPool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g := &curvePoint{
 | 
				
			||||||
 | 
							pool.Get().SetInt64(1),
 | 
				
			||||||
 | 
							pool.Get().SetInt64(-2),
 | 
				
			||||||
 | 
							pool.Get().SetInt64(1),
 | 
				
			||||||
 | 
							pool.Get().SetInt64(0),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x := pool.Get().SetInt64(32498273234)
 | 
				
			||||||
 | 
						X := newCurvePoint(pool).Mul(g, x, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						y := pool.Get().SetInt64(98732423523)
 | 
				
			||||||
 | 
						Y := newCurvePoint(pool).Mul(g, y, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s1 := newCurvePoint(pool).Mul(X, y, pool).MakeAffine(pool)
 | 
				
			||||||
 | 
						s2 := newCurvePoint(pool).Mul(Y, x, pool).MakeAffine(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if s1.x.Cmp(s2.x) != 0 ||
 | 
				
			||||||
 | 
							s2.x.Cmp(s1.x) != 0 {
 | 
				
			||||||
 | 
							t.Errorf("DH points don't match: (%s, %s) (%s, %s)", s1.x, s1.y, s2.x, s2.y)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pool.Put(x)
 | 
				
			||||||
 | 
						X.Put(pool)
 | 
				
			||||||
 | 
						pool.Put(y)
 | 
				
			||||||
 | 
						Y.Put(pool)
 | 
				
			||||||
 | 
						s1.Put(pool)
 | 
				
			||||||
 | 
						s2.Put(pool)
 | 
				
			||||||
 | 
						g.Put(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c := pool.Count(); c > 0 {
 | 
				
			||||||
 | 
							t.Errorf("Pool count non-zero: %d\n", c)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestOrderG1(t *testing.T) {
 | 
				
			||||||
 | 
						g := new(G1).ScalarBaseMult(Order)
 | 
				
			||||||
 | 
						if !g.p.IsInfinity() {
 | 
				
			||||||
 | 
							t.Error("G1 has incorrect order")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						one := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1))
 | 
				
			||||||
 | 
						g.Add(g, one)
 | 
				
			||||||
 | 
						g.p.MakeAffine(nil)
 | 
				
			||||||
 | 
						if g.p.x.Cmp(one.p.x) != 0 || g.p.y.Cmp(one.p.y) != 0 {
 | 
				
			||||||
 | 
							t.Errorf("1+0 != 1 in G1")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestOrderG2(t *testing.T) {
 | 
				
			||||||
 | 
						g := new(G2).ScalarBaseMult(Order)
 | 
				
			||||||
 | 
						if !g.p.IsInfinity() {
 | 
				
			||||||
 | 
							t.Error("G2 has incorrect order")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						one := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1))
 | 
				
			||||||
 | 
						g.Add(g, one)
 | 
				
			||||||
 | 
						g.p.MakeAffine(nil)
 | 
				
			||||||
 | 
						if g.p.x.x.Cmp(one.p.x.x) != 0 ||
 | 
				
			||||||
 | 
							g.p.x.y.Cmp(one.p.x.y) != 0 ||
 | 
				
			||||||
 | 
							g.p.y.x.Cmp(one.p.y.x) != 0 ||
 | 
				
			||||||
 | 
							g.p.y.y.Cmp(one.p.y.y) != 0 {
 | 
				
			||||||
 | 
							t.Errorf("1+0 != 1 in G2")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestOrderGT(t *testing.T) {
 | 
				
			||||||
 | 
						gt := Pair(&G1{curveGen}, &G2{twistGen})
 | 
				
			||||||
 | 
						g := new(GT).ScalarMult(gt, Order)
 | 
				
			||||||
 | 
						if !g.p.IsOne() {
 | 
				
			||||||
 | 
							t.Error("GT has incorrect order")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestBilinearity(t *testing.T) {
 | 
				
			||||||
 | 
						for i := 0; i < 2; i++ {
 | 
				
			||||||
 | 
							a, p1, _ := RandomG1(rand.Reader)
 | 
				
			||||||
 | 
							b, p2, _ := RandomG2(rand.Reader)
 | 
				
			||||||
 | 
							e1 := Pair(p1, p2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							e2 := Pair(&G1{curveGen}, &G2{twistGen})
 | 
				
			||||||
 | 
							e2.ScalarMult(e2, a)
 | 
				
			||||||
 | 
							e2.ScalarMult(e2, b)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							minusE2 := new(GT).Neg(e2)
 | 
				
			||||||
 | 
							e1.Add(e1, minusE2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !e1.p.IsOne() {
 | 
				
			||||||
 | 
								t.Fatalf("bad pairing result: %s", e1)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestG1Marshal(t *testing.T) {
 | 
				
			||||||
 | 
						g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1))
 | 
				
			||||||
 | 
						form := g.Marshal()
 | 
				
			||||||
 | 
						_, ok := new(G1).Unmarshal(form)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							t.Fatalf("failed to unmarshal")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.ScalarBaseMult(Order)
 | 
				
			||||||
 | 
						form = g.Marshal()
 | 
				
			||||||
 | 
						g2, ok := new(G1).Unmarshal(form)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							t.Fatalf("failed to unmarshal ∞")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !g2.p.IsInfinity() {
 | 
				
			||||||
 | 
							t.Fatalf("∞ unmarshaled incorrectly")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestG2Marshal(t *testing.T) {
 | 
				
			||||||
 | 
						g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1))
 | 
				
			||||||
 | 
						form := g.Marshal()
 | 
				
			||||||
 | 
						_, ok := new(G2).Unmarshal(form)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							t.Fatalf("failed to unmarshal")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.ScalarBaseMult(Order)
 | 
				
			||||||
 | 
						form = g.Marshal()
 | 
				
			||||||
 | 
						g2, ok := new(G2).Unmarshal(form)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							t.Fatalf("failed to unmarshal ∞")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !g2.p.IsInfinity() {
 | 
				
			||||||
 | 
							t.Fatalf("∞ unmarshaled incorrectly")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestG1Identity(t *testing.T) {
 | 
				
			||||||
 | 
						g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(0))
 | 
				
			||||||
 | 
						if !g.p.IsInfinity() {
 | 
				
			||||||
 | 
							t.Error("failure")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestG2Identity(t *testing.T) {
 | 
				
			||||||
 | 
						g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(0))
 | 
				
			||||||
 | 
						if !g.p.IsInfinity() {
 | 
				
			||||||
 | 
							t.Error("failure")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestTripartiteDiffieHellman(t *testing.T) {
 | 
				
			||||||
 | 
						a, _ := rand.Int(rand.Reader, Order)
 | 
				
			||||||
 | 
						b, _ := rand.Int(rand.Reader, Order)
 | 
				
			||||||
 | 
						c, _ := rand.Int(rand.Reader, Order)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pa, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(a).Marshal())
 | 
				
			||||||
 | 
						qa, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(a).Marshal())
 | 
				
			||||||
 | 
						pb, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(b).Marshal())
 | 
				
			||||||
 | 
						qb, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(b).Marshal())
 | 
				
			||||||
 | 
						pc, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(c).Marshal())
 | 
				
			||||||
 | 
						qc, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(c).Marshal())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						k1 := Pair(pb, qc)
 | 
				
			||||||
 | 
						k1.ScalarMult(k1, a)
 | 
				
			||||||
 | 
						k1Bytes := k1.Marshal()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						k2 := Pair(pc, qa)
 | 
				
			||||||
 | 
						k2.ScalarMult(k2, b)
 | 
				
			||||||
 | 
						k2Bytes := k2.Marshal()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						k3 := Pair(pa, qb)
 | 
				
			||||||
 | 
						k3.ScalarMult(k3, c)
 | 
				
			||||||
 | 
						k3Bytes := k3.Marshal()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !bytes.Equal(k1Bytes, k2Bytes) || !bytes.Equal(k2Bytes, k3Bytes) {
 | 
				
			||||||
 | 
							t.Errorf("keys didn't agree")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func BenchmarkPairing(b *testing.B) {
 | 
				
			||||||
 | 
						for i := 0; i < b.N; i++ {
 | 
				
			||||||
 | 
							Pair(&G1{curveGen}, &G2{twistGen})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										44
									
								
								crypto/bn256/constants.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								crypto/bn256/constants.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					// Copyright 2012 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package bn256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func bigFromBase10(s string) *big.Int {
 | 
				
			||||||
 | 
						n, _ := new(big.Int).SetString(s, 10)
 | 
				
			||||||
 | 
						return n
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// u is the BN parameter that determines the prime: 1868033³.
 | 
				
			||||||
 | 
					var u = bigFromBase10("4965661367192848881")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// p is a prime over which we form a basic field: 36u⁴+36u³+24u²+6u+1.
 | 
				
			||||||
 | 
					var P = bigFromBase10("21888242871839275222246405745257275088696311157297823662689037894645226208583")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u²+6u+1.
 | 
				
			||||||
 | 
					var Order = bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// xiToPMinus1Over6 is ξ^((p-1)/6) where ξ = i+9.
 | 
				
			||||||
 | 
					var xiToPMinus1Over6 = &gfP2{bigFromBase10("16469823323077808223889137241176536799009286646108169935659301613961712198316"), bigFromBase10("8376118865763821496583973867626364092589906065868298776909617916018768340080")}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// xiToPMinus1Over3 is ξ^((p-1)/3) where ξ = i+9.
 | 
				
			||||||
 | 
					var xiToPMinus1Over3 = &gfP2{bigFromBase10("10307601595873709700152284273816112264069230130616436755625194854815875713954"), bigFromBase10("21575463638280843010398324269430826099269044274347216827212613867836435027261")}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// xiToPMinus1Over2 is ξ^((p-1)/2) where ξ = i+9.
 | 
				
			||||||
 | 
					var xiToPMinus1Over2 = &gfP2{bigFromBase10("3505843767911556378687030309984248845540243509899259641013678093033130930403"), bigFromBase10("2821565182194536844548159561693502659359617185244120367078079554186484126554")}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// xiToPSquaredMinus1Over3 is ξ^((p²-1)/3) where ξ = i+9.
 | 
				
			||||||
 | 
					var xiToPSquaredMinus1Over3 = bigFromBase10("21888242871839275220042445260109153167277707414472061641714758635765020556616")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// xiTo2PSquaredMinus2Over3 is ξ^((2p²-2)/3) where ξ = i+9 (a cubic root of unity, mod p).
 | 
				
			||||||
 | 
					var xiTo2PSquaredMinus2Over3 = bigFromBase10("2203960485148121921418603742825762020974279258880205651966")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// xiToPSquaredMinus1Over6 is ξ^((1p²-1)/6) where ξ = i+9 (a cubic root of -1, mod p).
 | 
				
			||||||
 | 
					var xiToPSquaredMinus1Over6 = bigFromBase10("21888242871839275220042445260109153167277707414472061641714758635765020556617")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// xiTo2PMinus2Over3 is ξ^((2p-2)/3) where ξ = i+9.
 | 
				
			||||||
 | 
					var xiTo2PMinus2Over3 = &gfP2{bigFromBase10("19937756971775647987995932169929341994314640652964949448313374472400716661030"), bigFromBase10("2581911344467009335267311115468803099551665605076196740867805258568234346338")}
 | 
				
			||||||
							
								
								
									
										278
									
								
								crypto/bn256/curve.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										278
									
								
								crypto/bn256/curve.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,278 @@
 | 
				
			|||||||
 | 
					// Copyright 2012 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package bn256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// curvePoint implements the elliptic curve y²=x³+3. Points are kept in
 | 
				
			||||||
 | 
					// Jacobian form and t=z² when valid. G₁ is the set of points of this curve on
 | 
				
			||||||
 | 
					// GF(p).
 | 
				
			||||||
 | 
					type curvePoint struct {
 | 
				
			||||||
 | 
						x, y, z, t *big.Int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var curveB = new(big.Int).SetInt64(3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// curveGen is the generator of G₁.
 | 
				
			||||||
 | 
					var curveGen = &curvePoint{
 | 
				
			||||||
 | 
						new(big.Int).SetInt64(1),
 | 
				
			||||||
 | 
						new(big.Int).SetInt64(-2),
 | 
				
			||||||
 | 
						new(big.Int).SetInt64(1),
 | 
				
			||||||
 | 
						new(big.Int).SetInt64(1),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newCurvePoint(pool *bnPool) *curvePoint {
 | 
				
			||||||
 | 
						return &curvePoint{
 | 
				
			||||||
 | 
							pool.Get(),
 | 
				
			||||||
 | 
							pool.Get(),
 | 
				
			||||||
 | 
							pool.Get(),
 | 
				
			||||||
 | 
							pool.Get(),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *curvePoint) String() string {
 | 
				
			||||||
 | 
						c.MakeAffine(new(bnPool))
 | 
				
			||||||
 | 
						return "(" + c.x.String() + ", " + c.y.String() + ")"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *curvePoint) Put(pool *bnPool) {
 | 
				
			||||||
 | 
						pool.Put(c.x)
 | 
				
			||||||
 | 
						pool.Put(c.y)
 | 
				
			||||||
 | 
						pool.Put(c.z)
 | 
				
			||||||
 | 
						pool.Put(c.t)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *curvePoint) Set(a *curvePoint) {
 | 
				
			||||||
 | 
						c.x.Set(a.x)
 | 
				
			||||||
 | 
						c.y.Set(a.y)
 | 
				
			||||||
 | 
						c.z.Set(a.z)
 | 
				
			||||||
 | 
						c.t.Set(a.t)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsOnCurve returns true iff c is on the curve where c must be in affine form.
 | 
				
			||||||
 | 
					func (c *curvePoint) IsOnCurve() bool {
 | 
				
			||||||
 | 
						yy := new(big.Int).Mul(c.y, c.y)
 | 
				
			||||||
 | 
						xxx := new(big.Int).Mul(c.x, c.x)
 | 
				
			||||||
 | 
						xxx.Mul(xxx, c.x)
 | 
				
			||||||
 | 
						yy.Sub(yy, xxx)
 | 
				
			||||||
 | 
						yy.Sub(yy, curveB)
 | 
				
			||||||
 | 
						if yy.Sign() < 0 || yy.Cmp(P) >= 0 {
 | 
				
			||||||
 | 
							yy.Mod(yy, P)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return yy.Sign() == 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *curvePoint) SetInfinity() {
 | 
				
			||||||
 | 
						c.z.SetInt64(0)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *curvePoint) IsInfinity() bool {
 | 
				
			||||||
 | 
						return c.z.Sign() == 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) {
 | 
				
			||||||
 | 
						if a.IsInfinity() {
 | 
				
			||||||
 | 
							c.Set(b)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if b.IsInfinity() {
 | 
				
			||||||
 | 
							c.Set(a)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2]
 | 
				
			||||||
 | 
						// by [u1:s1:z1·z2] and [u2:s2:z1·z2]
 | 
				
			||||||
 | 
						// where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³
 | 
				
			||||||
 | 
						z1z1 := pool.Get().Mul(a.z, a.z)
 | 
				
			||||||
 | 
						z1z1.Mod(z1z1, P)
 | 
				
			||||||
 | 
						z2z2 := pool.Get().Mul(b.z, b.z)
 | 
				
			||||||
 | 
						z2z2.Mod(z2z2, P)
 | 
				
			||||||
 | 
						u1 := pool.Get().Mul(a.x, z2z2)
 | 
				
			||||||
 | 
						u1.Mod(u1, P)
 | 
				
			||||||
 | 
						u2 := pool.Get().Mul(b.x, z1z1)
 | 
				
			||||||
 | 
						u2.Mod(u2, P)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t := pool.Get().Mul(b.z, z2z2)
 | 
				
			||||||
 | 
						t.Mod(t, P)
 | 
				
			||||||
 | 
						s1 := pool.Get().Mul(a.y, t)
 | 
				
			||||||
 | 
						s1.Mod(s1, P)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Mul(a.z, z1z1)
 | 
				
			||||||
 | 
						t.Mod(t, P)
 | 
				
			||||||
 | 
						s2 := pool.Get().Mul(b.y, t)
 | 
				
			||||||
 | 
						s2.Mod(s2, P)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Compute x = (2h)²(s²-u1-u2)
 | 
				
			||||||
 | 
						// where s = (s2-s1)/(u2-u1) is the slope of the line through
 | 
				
			||||||
 | 
						// (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below.
 | 
				
			||||||
 | 
						// This is also:
 | 
				
			||||||
 | 
						// 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1)
 | 
				
			||||||
 | 
						//                        = r² - j - 2v
 | 
				
			||||||
 | 
						// with the notations below.
 | 
				
			||||||
 | 
						h := pool.Get().Sub(u2, u1)
 | 
				
			||||||
 | 
						xEqual := h.Sign() == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Add(h, h)
 | 
				
			||||||
 | 
						// i = 4h²
 | 
				
			||||||
 | 
						i := pool.Get().Mul(t, t)
 | 
				
			||||||
 | 
						i.Mod(i, P)
 | 
				
			||||||
 | 
						// j = 4h³
 | 
				
			||||||
 | 
						j := pool.Get().Mul(h, i)
 | 
				
			||||||
 | 
						j.Mod(j, P)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Sub(s2, s1)
 | 
				
			||||||
 | 
						yEqual := t.Sign() == 0
 | 
				
			||||||
 | 
						if xEqual && yEqual {
 | 
				
			||||||
 | 
							c.Double(a, pool)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						r := pool.Get().Add(t, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v := pool.Get().Mul(u1, i)
 | 
				
			||||||
 | 
						v.Mod(v, P)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// t4 = 4(s2-s1)²
 | 
				
			||||||
 | 
						t4 := pool.Get().Mul(r, r)
 | 
				
			||||||
 | 
						t4.Mod(t4, P)
 | 
				
			||||||
 | 
						t.Add(v, v)
 | 
				
			||||||
 | 
						t6 := pool.Get().Sub(t4, j)
 | 
				
			||||||
 | 
						c.x.Sub(t6, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set y = -(2h)³(s1 + s*(x/4h²-u1))
 | 
				
			||||||
 | 
						// This is also
 | 
				
			||||||
 | 
						// y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j
 | 
				
			||||||
 | 
						t.Sub(v, c.x) // t7
 | 
				
			||||||
 | 
						t4.Mul(s1, j) // t8
 | 
				
			||||||
 | 
						t4.Mod(t4, P)
 | 
				
			||||||
 | 
						t6.Add(t4, t4) // t9
 | 
				
			||||||
 | 
						t4.Mul(r, t)   // t10
 | 
				
			||||||
 | 
						t4.Mod(t4, P)
 | 
				
			||||||
 | 
						c.y.Sub(t4, t6)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2
 | 
				
			||||||
 | 
						t.Add(a.z, b.z) // t11
 | 
				
			||||||
 | 
						t4.Mul(t, t)    // t12
 | 
				
			||||||
 | 
						t4.Mod(t4, P)
 | 
				
			||||||
 | 
						t.Sub(t4, z1z1) // t13
 | 
				
			||||||
 | 
						t4.Sub(t, z2z2) // t14
 | 
				
			||||||
 | 
						c.z.Mul(t4, h)
 | 
				
			||||||
 | 
						c.z.Mod(c.z, P)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pool.Put(z1z1)
 | 
				
			||||||
 | 
						pool.Put(z2z2)
 | 
				
			||||||
 | 
						pool.Put(u1)
 | 
				
			||||||
 | 
						pool.Put(u2)
 | 
				
			||||||
 | 
						pool.Put(t)
 | 
				
			||||||
 | 
						pool.Put(s1)
 | 
				
			||||||
 | 
						pool.Put(s2)
 | 
				
			||||||
 | 
						pool.Put(h)
 | 
				
			||||||
 | 
						pool.Put(i)
 | 
				
			||||||
 | 
						pool.Put(j)
 | 
				
			||||||
 | 
						pool.Put(r)
 | 
				
			||||||
 | 
						pool.Put(v)
 | 
				
			||||||
 | 
						pool.Put(t4)
 | 
				
			||||||
 | 
						pool.Put(t6)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *curvePoint) Double(a *curvePoint, pool *bnPool) {
 | 
				
			||||||
 | 
						// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
 | 
				
			||||||
 | 
						A := pool.Get().Mul(a.x, a.x)
 | 
				
			||||||
 | 
						A.Mod(A, P)
 | 
				
			||||||
 | 
						B := pool.Get().Mul(a.y, a.y)
 | 
				
			||||||
 | 
						B.Mod(B, P)
 | 
				
			||||||
 | 
						C := pool.Get().Mul(B, B)
 | 
				
			||||||
 | 
						C.Mod(C, P)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t := pool.Get().Add(a.x, B)
 | 
				
			||||||
 | 
						t2 := pool.Get().Mul(t, t)
 | 
				
			||||||
 | 
						t2.Mod(t2, P)
 | 
				
			||||||
 | 
						t.Sub(t2, A)
 | 
				
			||||||
 | 
						t2.Sub(t, C)
 | 
				
			||||||
 | 
						d := pool.Get().Add(t2, t2)
 | 
				
			||||||
 | 
						t.Add(A, A)
 | 
				
			||||||
 | 
						e := pool.Get().Add(t, A)
 | 
				
			||||||
 | 
						f := pool.Get().Mul(e, e)
 | 
				
			||||||
 | 
						f.Mod(f, P)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Add(d, d)
 | 
				
			||||||
 | 
						c.x.Sub(f, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Add(C, C)
 | 
				
			||||||
 | 
						t2.Add(t, t)
 | 
				
			||||||
 | 
						t.Add(t2, t2)
 | 
				
			||||||
 | 
						c.y.Sub(d, c.x)
 | 
				
			||||||
 | 
						t2.Mul(e, c.y)
 | 
				
			||||||
 | 
						t2.Mod(t2, P)
 | 
				
			||||||
 | 
						c.y.Sub(t2, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Mul(a.y, a.z)
 | 
				
			||||||
 | 
						t.Mod(t, P)
 | 
				
			||||||
 | 
						c.z.Add(t, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pool.Put(A)
 | 
				
			||||||
 | 
						pool.Put(B)
 | 
				
			||||||
 | 
						pool.Put(C)
 | 
				
			||||||
 | 
						pool.Put(t)
 | 
				
			||||||
 | 
						pool.Put(t2)
 | 
				
			||||||
 | 
						pool.Put(d)
 | 
				
			||||||
 | 
						pool.Put(e)
 | 
				
			||||||
 | 
						pool.Put(f)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint {
 | 
				
			||||||
 | 
						sum := newCurvePoint(pool)
 | 
				
			||||||
 | 
						sum.SetInfinity()
 | 
				
			||||||
 | 
						t := newCurvePoint(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := scalar.BitLen(); i >= 0; i-- {
 | 
				
			||||||
 | 
							t.Double(sum, pool)
 | 
				
			||||||
 | 
							if scalar.Bit(i) != 0 {
 | 
				
			||||||
 | 
								sum.Add(t, a, pool)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								sum.Set(t)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c.Set(sum)
 | 
				
			||||||
 | 
						sum.Put(pool)
 | 
				
			||||||
 | 
						t.Put(pool)
 | 
				
			||||||
 | 
						return c
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint {
 | 
				
			||||||
 | 
						if words := c.z.Bits(); len(words) == 1 && words[0] == 1 {
 | 
				
			||||||
 | 
							return c
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						zInv := pool.Get().ModInverse(c.z, P)
 | 
				
			||||||
 | 
						t := pool.Get().Mul(c.y, zInv)
 | 
				
			||||||
 | 
						t.Mod(t, P)
 | 
				
			||||||
 | 
						zInv2 := pool.Get().Mul(zInv, zInv)
 | 
				
			||||||
 | 
						zInv2.Mod(zInv2, P)
 | 
				
			||||||
 | 
						c.y.Mul(t, zInv2)
 | 
				
			||||||
 | 
						c.y.Mod(c.y, P)
 | 
				
			||||||
 | 
						t.Mul(c.x, zInv2)
 | 
				
			||||||
 | 
						t.Mod(t, P)
 | 
				
			||||||
 | 
						c.x.Set(t)
 | 
				
			||||||
 | 
						c.z.SetInt64(1)
 | 
				
			||||||
 | 
						c.t.SetInt64(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pool.Put(zInv)
 | 
				
			||||||
 | 
						pool.Put(t)
 | 
				
			||||||
 | 
						pool.Put(zInv2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return c
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *curvePoint) Negative(a *curvePoint) {
 | 
				
			||||||
 | 
						c.x.Set(a.x)
 | 
				
			||||||
 | 
						c.y.Neg(a.y)
 | 
				
			||||||
 | 
						c.z.Set(a.z)
 | 
				
			||||||
 | 
						c.t.SetInt64(0)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										43
									
								
								crypto/bn256/example_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								crypto/bn256/example_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					// Copyright 2012 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package bn256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/rand"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ExamplePair() {
 | 
				
			||||||
 | 
						// This implements the tripartite Diffie-Hellman algorithm from "A One
 | 
				
			||||||
 | 
						// Round Protocol for Tripartite Diffie-Hellman", A. Joux.
 | 
				
			||||||
 | 
						// http://www.springerlink.com/content/cddc57yyva0hburb/fulltext.pdf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Each of three parties, a, b and c, generate a private value.
 | 
				
			||||||
 | 
						a, _ := rand.Int(rand.Reader, Order)
 | 
				
			||||||
 | 
						b, _ := rand.Int(rand.Reader, Order)
 | 
				
			||||||
 | 
						c, _ := rand.Int(rand.Reader, Order)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Then each party calculates g₁ and g₂ times their private value.
 | 
				
			||||||
 | 
						pa := new(G1).ScalarBaseMult(a)
 | 
				
			||||||
 | 
						qa := new(G2).ScalarBaseMult(a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pb := new(G1).ScalarBaseMult(b)
 | 
				
			||||||
 | 
						qb := new(G2).ScalarBaseMult(b)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pc := new(G1).ScalarBaseMult(c)
 | 
				
			||||||
 | 
						qc := new(G2).ScalarBaseMult(c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Now each party exchanges its public values with the other two and
 | 
				
			||||||
 | 
						// all parties can calculate the shared key.
 | 
				
			||||||
 | 
						k1 := Pair(pb, qc)
 | 
				
			||||||
 | 
						k1.ScalarMult(k1, a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						k2 := Pair(pc, qa)
 | 
				
			||||||
 | 
						k2.ScalarMult(k2, b)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						k3 := Pair(pa, qb)
 | 
				
			||||||
 | 
						k3.ScalarMult(k3, c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// k1, k2 and k3 will all be equal.
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										200
									
								
								crypto/bn256/gfp12.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								crypto/bn256/gfp12.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,200 @@
 | 
				
			|||||||
 | 
					// Copyright 2012 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package bn256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// For details of the algorithms used, see "Multiplication and Squaring on
 | 
				
			||||||
 | 
					// Pairing-Friendly Fields, Devegili et al.
 | 
				
			||||||
 | 
					// http://eprint.iacr.org/2006/471.pdf.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// gfP12 implements the field of size p¹² as a quadratic extension of gfP6
 | 
				
			||||||
 | 
					// where ω²=τ.
 | 
				
			||||||
 | 
					type gfP12 struct {
 | 
				
			||||||
 | 
						x, y *gfP6 // value is xω + y
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newGFp12(pool *bnPool) *gfP12 {
 | 
				
			||||||
 | 
						return &gfP12{newGFp6(pool), newGFp6(pool)}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP12) String() string {
 | 
				
			||||||
 | 
						return "(" + e.x.String() + "," + e.y.String() + ")"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP12) Put(pool *bnPool) {
 | 
				
			||||||
 | 
						e.x.Put(pool)
 | 
				
			||||||
 | 
						e.y.Put(pool)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP12) Set(a *gfP12) *gfP12 {
 | 
				
			||||||
 | 
						e.x.Set(a.x)
 | 
				
			||||||
 | 
						e.y.Set(a.y)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP12) SetZero() *gfP12 {
 | 
				
			||||||
 | 
						e.x.SetZero()
 | 
				
			||||||
 | 
						e.y.SetZero()
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP12) SetOne() *gfP12 {
 | 
				
			||||||
 | 
						e.x.SetZero()
 | 
				
			||||||
 | 
						e.y.SetOne()
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP12) Minimal() {
 | 
				
			||||||
 | 
						e.x.Minimal()
 | 
				
			||||||
 | 
						e.y.Minimal()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP12) IsZero() bool {
 | 
				
			||||||
 | 
						e.Minimal()
 | 
				
			||||||
 | 
						return e.x.IsZero() && e.y.IsZero()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP12) IsOne() bool {
 | 
				
			||||||
 | 
						e.Minimal()
 | 
				
			||||||
 | 
						return e.x.IsZero() && e.y.IsOne()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP12) Conjugate(a *gfP12) *gfP12 {
 | 
				
			||||||
 | 
						e.x.Negative(a.x)
 | 
				
			||||||
 | 
						e.y.Set(a.y)
 | 
				
			||||||
 | 
						return a
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP12) Negative(a *gfP12) *gfP12 {
 | 
				
			||||||
 | 
						e.x.Negative(a.x)
 | 
				
			||||||
 | 
						e.y.Negative(a.y)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p
 | 
				
			||||||
 | 
					func (e *gfP12) Frobenius(a *gfP12, pool *bnPool) *gfP12 {
 | 
				
			||||||
 | 
						e.x.Frobenius(a.x, pool)
 | 
				
			||||||
 | 
						e.y.Frobenius(a.y, pool)
 | 
				
			||||||
 | 
						e.x.MulScalar(e.x, xiToPMinus1Over6, pool)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p²
 | 
				
			||||||
 | 
					func (e *gfP12) FrobeniusP2(a *gfP12, pool *bnPool) *gfP12 {
 | 
				
			||||||
 | 
						e.x.FrobeniusP2(a.x)
 | 
				
			||||||
 | 
						e.x.MulGFP(e.x, xiToPSquaredMinus1Over6)
 | 
				
			||||||
 | 
						e.y.FrobeniusP2(a.y)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP12) Add(a, b *gfP12) *gfP12 {
 | 
				
			||||||
 | 
						e.x.Add(a.x, b.x)
 | 
				
			||||||
 | 
						e.y.Add(a.y, b.y)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP12) Sub(a, b *gfP12) *gfP12 {
 | 
				
			||||||
 | 
						e.x.Sub(a.x, b.x)
 | 
				
			||||||
 | 
						e.y.Sub(a.y, b.y)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 {
 | 
				
			||||||
 | 
						tx := newGFp6(pool)
 | 
				
			||||||
 | 
						tx.Mul(a.x, b.y, pool)
 | 
				
			||||||
 | 
						t := newGFp6(pool)
 | 
				
			||||||
 | 
						t.Mul(b.x, a.y, pool)
 | 
				
			||||||
 | 
						tx.Add(tx, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ty := newGFp6(pool)
 | 
				
			||||||
 | 
						ty.Mul(a.y, b.y, pool)
 | 
				
			||||||
 | 
						t.Mul(a.x, b.x, pool)
 | 
				
			||||||
 | 
						t.MulTau(t, pool)
 | 
				
			||||||
 | 
						e.y.Add(ty, t)
 | 
				
			||||||
 | 
						e.x.Set(tx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tx.Put(pool)
 | 
				
			||||||
 | 
						ty.Put(pool)
 | 
				
			||||||
 | 
						t.Put(pool)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 {
 | 
				
			||||||
 | 
						e.x.Mul(e.x, b, pool)
 | 
				
			||||||
 | 
						e.y.Mul(e.y, b, pool)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 {
 | 
				
			||||||
 | 
						sum := newGFp12(pool)
 | 
				
			||||||
 | 
						sum.SetOne()
 | 
				
			||||||
 | 
						t := newGFp12(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := power.BitLen() - 1; i >= 0; i-- {
 | 
				
			||||||
 | 
							t.Square(sum, pool)
 | 
				
			||||||
 | 
							if power.Bit(i) != 0 {
 | 
				
			||||||
 | 
								sum.Mul(t, a, pool)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								sum.Set(t)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c.Set(sum)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sum.Put(pool)
 | 
				
			||||||
 | 
						t.Put(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return c
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 {
 | 
				
			||||||
 | 
						// Complex squaring algorithm
 | 
				
			||||||
 | 
						v0 := newGFp6(pool)
 | 
				
			||||||
 | 
						v0.Mul(a.x, a.y, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t := newGFp6(pool)
 | 
				
			||||||
 | 
						t.MulTau(a.x, pool)
 | 
				
			||||||
 | 
						t.Add(a.y, t)
 | 
				
			||||||
 | 
						ty := newGFp6(pool)
 | 
				
			||||||
 | 
						ty.Add(a.x, a.y)
 | 
				
			||||||
 | 
						ty.Mul(ty, t, pool)
 | 
				
			||||||
 | 
						ty.Sub(ty, v0)
 | 
				
			||||||
 | 
						t.MulTau(v0, pool)
 | 
				
			||||||
 | 
						ty.Sub(ty, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e.y.Set(ty)
 | 
				
			||||||
 | 
						e.x.Double(v0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v0.Put(pool)
 | 
				
			||||||
 | 
						t.Put(pool)
 | 
				
			||||||
 | 
						ty.Put(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP12) Invert(a *gfP12, pool *bnPool) *gfP12 {
 | 
				
			||||||
 | 
						// See "Implementing cryptographic pairings", M. Scott, section 3.2.
 | 
				
			||||||
 | 
						// ftp://136.206.11.249/pub/crypto/pairings.pdf
 | 
				
			||||||
 | 
						t1 := newGFp6(pool)
 | 
				
			||||||
 | 
						t2 := newGFp6(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t1.Square(a.x, pool)
 | 
				
			||||||
 | 
						t2.Square(a.y, pool)
 | 
				
			||||||
 | 
						t1.MulTau(t1, pool)
 | 
				
			||||||
 | 
						t1.Sub(t2, t1)
 | 
				
			||||||
 | 
						t2.Invert(t1, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e.x.Negative(a.x)
 | 
				
			||||||
 | 
						e.y.Set(a.y)
 | 
				
			||||||
 | 
						e.MulScalar(e, t2, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t1.Put(pool)
 | 
				
			||||||
 | 
						t2.Put(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										227
									
								
								crypto/bn256/gfp2.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								crypto/bn256/gfp2.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,227 @@
 | 
				
			|||||||
 | 
					// Copyright 2012 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package bn256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// For details of the algorithms used, see "Multiplication and Squaring on
 | 
				
			||||||
 | 
					// Pairing-Friendly Fields, Devegili et al.
 | 
				
			||||||
 | 
					// http://eprint.iacr.org/2006/471.pdf.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// gfP2 implements a field of size p² as a quadratic extension of the base
 | 
				
			||||||
 | 
					// field where i²=-1.
 | 
				
			||||||
 | 
					type gfP2 struct {
 | 
				
			||||||
 | 
						x, y *big.Int // value is xi+y.
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newGFp2(pool *bnPool) *gfP2 {
 | 
				
			||||||
 | 
						return &gfP2{pool.Get(), pool.Get()}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) String() string {
 | 
				
			||||||
 | 
						x := new(big.Int).Mod(e.x, P)
 | 
				
			||||||
 | 
						y := new(big.Int).Mod(e.y, P)
 | 
				
			||||||
 | 
						return "(" + x.String() + "," + y.String() + ")"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) Put(pool *bnPool) {
 | 
				
			||||||
 | 
						pool.Put(e.x)
 | 
				
			||||||
 | 
						pool.Put(e.y)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) Set(a *gfP2) *gfP2 {
 | 
				
			||||||
 | 
						e.x.Set(a.x)
 | 
				
			||||||
 | 
						e.y.Set(a.y)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) SetZero() *gfP2 {
 | 
				
			||||||
 | 
						e.x.SetInt64(0)
 | 
				
			||||||
 | 
						e.y.SetInt64(0)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) SetOne() *gfP2 {
 | 
				
			||||||
 | 
						e.x.SetInt64(0)
 | 
				
			||||||
 | 
						e.y.SetInt64(1)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) Minimal() {
 | 
				
			||||||
 | 
						if e.x.Sign() < 0 || e.x.Cmp(P) >= 0 {
 | 
				
			||||||
 | 
							e.x.Mod(e.x, P)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if e.y.Sign() < 0 || e.y.Cmp(P) >= 0 {
 | 
				
			||||||
 | 
							e.y.Mod(e.y, P)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) IsZero() bool {
 | 
				
			||||||
 | 
						return e.x.Sign() == 0 && e.y.Sign() == 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) IsOne() bool {
 | 
				
			||||||
 | 
						if e.x.Sign() != 0 {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						words := e.y.Bits()
 | 
				
			||||||
 | 
						return len(words) == 1 && words[0] == 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) Conjugate(a *gfP2) *gfP2 {
 | 
				
			||||||
 | 
						e.y.Set(a.y)
 | 
				
			||||||
 | 
						e.x.Neg(a.x)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) Negative(a *gfP2) *gfP2 {
 | 
				
			||||||
 | 
						e.x.Neg(a.x)
 | 
				
			||||||
 | 
						e.y.Neg(a.y)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) Add(a, b *gfP2) *gfP2 {
 | 
				
			||||||
 | 
						e.x.Add(a.x, b.x)
 | 
				
			||||||
 | 
						e.y.Add(a.y, b.y)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) Sub(a, b *gfP2) *gfP2 {
 | 
				
			||||||
 | 
						e.x.Sub(a.x, b.x)
 | 
				
			||||||
 | 
						e.y.Sub(a.y, b.y)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) Double(a *gfP2) *gfP2 {
 | 
				
			||||||
 | 
						e.x.Lsh(a.x, 1)
 | 
				
			||||||
 | 
						e.y.Lsh(a.y, 1)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 {
 | 
				
			||||||
 | 
						sum := newGFp2(pool)
 | 
				
			||||||
 | 
						sum.SetOne()
 | 
				
			||||||
 | 
						t := newGFp2(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := power.BitLen() - 1; i >= 0; i-- {
 | 
				
			||||||
 | 
							t.Square(sum, pool)
 | 
				
			||||||
 | 
							if power.Bit(i) != 0 {
 | 
				
			||||||
 | 
								sum.Mul(t, a, pool)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								sum.Set(t)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c.Set(sum)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sum.Put(pool)
 | 
				
			||||||
 | 
						t.Put(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return c
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// See "Multiplication and Squaring in Pairing-Friendly Fields",
 | 
				
			||||||
 | 
					// http://eprint.iacr.org/2006/471.pdf
 | 
				
			||||||
 | 
					func (e *gfP2) Mul(a, b *gfP2, pool *bnPool) *gfP2 {
 | 
				
			||||||
 | 
						tx := pool.Get().Mul(a.x, b.y)
 | 
				
			||||||
 | 
						t := pool.Get().Mul(b.x, a.y)
 | 
				
			||||||
 | 
						tx.Add(tx, t)
 | 
				
			||||||
 | 
						tx.Mod(tx, P)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ty := pool.Get().Mul(a.y, b.y)
 | 
				
			||||||
 | 
						t.Mul(a.x, b.x)
 | 
				
			||||||
 | 
						ty.Sub(ty, t)
 | 
				
			||||||
 | 
						e.y.Mod(ty, P)
 | 
				
			||||||
 | 
						e.x.Set(tx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pool.Put(tx)
 | 
				
			||||||
 | 
						pool.Put(ty)
 | 
				
			||||||
 | 
						pool.Put(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) MulScalar(a *gfP2, b *big.Int) *gfP2 {
 | 
				
			||||||
 | 
						e.x.Mul(a.x, b)
 | 
				
			||||||
 | 
						e.y.Mul(a.y, b)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MulXi sets e=ξa where ξ=i+9 and then returns e.
 | 
				
			||||||
 | 
					func (e *gfP2) MulXi(a *gfP2, pool *bnPool) *gfP2 {
 | 
				
			||||||
 | 
						// (xi+y)(i+3) = (9x+y)i+(9y-x)
 | 
				
			||||||
 | 
						tx := pool.Get().Lsh(a.x, 3)
 | 
				
			||||||
 | 
						tx.Add(tx, a.x)
 | 
				
			||||||
 | 
						tx.Add(tx, a.y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ty := pool.Get().Lsh(a.y, 3)
 | 
				
			||||||
 | 
						ty.Add(ty, a.y)
 | 
				
			||||||
 | 
						ty.Sub(ty, a.x)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e.x.Set(tx)
 | 
				
			||||||
 | 
						e.y.Set(ty)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pool.Put(tx)
 | 
				
			||||||
 | 
						pool.Put(ty)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) Square(a *gfP2, pool *bnPool) *gfP2 {
 | 
				
			||||||
 | 
						// Complex squaring algorithm:
 | 
				
			||||||
 | 
						// (xi+b)² = (x+y)(y-x) + 2*i*x*y
 | 
				
			||||||
 | 
						t1 := pool.Get().Sub(a.y, a.x)
 | 
				
			||||||
 | 
						t2 := pool.Get().Add(a.x, a.y)
 | 
				
			||||||
 | 
						ty := pool.Get().Mul(t1, t2)
 | 
				
			||||||
 | 
						ty.Mod(ty, P)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t1.Mul(a.x, a.y)
 | 
				
			||||||
 | 
						t1.Lsh(t1, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e.x.Mod(t1, P)
 | 
				
			||||||
 | 
						e.y.Set(ty)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pool.Put(t1)
 | 
				
			||||||
 | 
						pool.Put(t2)
 | 
				
			||||||
 | 
						pool.Put(ty)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) Invert(a *gfP2, pool *bnPool) *gfP2 {
 | 
				
			||||||
 | 
						// See "Implementing cryptographic pairings", M. Scott, section 3.2.
 | 
				
			||||||
 | 
						// ftp://136.206.11.249/pub/crypto/pairings.pdf
 | 
				
			||||||
 | 
						t := pool.Get()
 | 
				
			||||||
 | 
						t.Mul(a.y, a.y)
 | 
				
			||||||
 | 
						t2 := pool.Get()
 | 
				
			||||||
 | 
						t2.Mul(a.x, a.x)
 | 
				
			||||||
 | 
						t.Add(t, t2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inv := pool.Get()
 | 
				
			||||||
 | 
						inv.ModInverse(t, P)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e.x.Neg(a.x)
 | 
				
			||||||
 | 
						e.x.Mul(e.x, inv)
 | 
				
			||||||
 | 
						e.x.Mod(e.x, P)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e.y.Mul(a.y, inv)
 | 
				
			||||||
 | 
						e.y.Mod(e.y, P)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pool.Put(t)
 | 
				
			||||||
 | 
						pool.Put(t2)
 | 
				
			||||||
 | 
						pool.Put(inv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) Real() *big.Int {
 | 
				
			||||||
 | 
						return e.x
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP2) Imag() *big.Int {
 | 
				
			||||||
 | 
						return e.y
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										296
									
								
								crypto/bn256/gfp6.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										296
									
								
								crypto/bn256/gfp6.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,296 @@
 | 
				
			|||||||
 | 
					// Copyright 2012 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package bn256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// For details of the algorithms used, see "Multiplication and Squaring on
 | 
				
			||||||
 | 
					// Pairing-Friendly Fields, Devegili et al.
 | 
				
			||||||
 | 
					// http://eprint.iacr.org/2006/471.pdf.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ
 | 
				
			||||||
 | 
					// and ξ=i+9.
 | 
				
			||||||
 | 
					type gfP6 struct {
 | 
				
			||||||
 | 
						x, y, z *gfP2 // value is xτ² + yτ + z
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newGFp6(pool *bnPool) *gfP6 {
 | 
				
			||||||
 | 
						return &gfP6{newGFp2(pool), newGFp2(pool), newGFp2(pool)}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) String() string {
 | 
				
			||||||
 | 
						return "(" + e.x.String() + "," + e.y.String() + "," + e.z.String() + ")"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) Put(pool *bnPool) {
 | 
				
			||||||
 | 
						e.x.Put(pool)
 | 
				
			||||||
 | 
						e.y.Put(pool)
 | 
				
			||||||
 | 
						e.z.Put(pool)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) Set(a *gfP6) *gfP6 {
 | 
				
			||||||
 | 
						e.x.Set(a.x)
 | 
				
			||||||
 | 
						e.y.Set(a.y)
 | 
				
			||||||
 | 
						e.z.Set(a.z)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) SetZero() *gfP6 {
 | 
				
			||||||
 | 
						e.x.SetZero()
 | 
				
			||||||
 | 
						e.y.SetZero()
 | 
				
			||||||
 | 
						e.z.SetZero()
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) SetOne() *gfP6 {
 | 
				
			||||||
 | 
						e.x.SetZero()
 | 
				
			||||||
 | 
						e.y.SetZero()
 | 
				
			||||||
 | 
						e.z.SetOne()
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) Minimal() {
 | 
				
			||||||
 | 
						e.x.Minimal()
 | 
				
			||||||
 | 
						e.y.Minimal()
 | 
				
			||||||
 | 
						e.z.Minimal()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) IsZero() bool {
 | 
				
			||||||
 | 
						return e.x.IsZero() && e.y.IsZero() && e.z.IsZero()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) IsOne() bool {
 | 
				
			||||||
 | 
						return e.x.IsZero() && e.y.IsZero() && e.z.IsOne()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) Negative(a *gfP6) *gfP6 {
 | 
				
			||||||
 | 
						e.x.Negative(a.x)
 | 
				
			||||||
 | 
						e.y.Negative(a.y)
 | 
				
			||||||
 | 
						e.z.Negative(a.z)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) Frobenius(a *gfP6, pool *bnPool) *gfP6 {
 | 
				
			||||||
 | 
						e.x.Conjugate(a.x)
 | 
				
			||||||
 | 
						e.y.Conjugate(a.y)
 | 
				
			||||||
 | 
						e.z.Conjugate(a.z)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e.x.Mul(e.x, xiTo2PMinus2Over3, pool)
 | 
				
			||||||
 | 
						e.y.Mul(e.y, xiToPMinus1Over3, pool)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z
 | 
				
			||||||
 | 
					func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 {
 | 
				
			||||||
 | 
						// τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3)
 | 
				
			||||||
 | 
						e.x.MulScalar(a.x, xiTo2PSquaredMinus2Over3)
 | 
				
			||||||
 | 
						// τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3)
 | 
				
			||||||
 | 
						e.y.MulScalar(a.y, xiToPSquaredMinus1Over3)
 | 
				
			||||||
 | 
						e.z.Set(a.z)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) Add(a, b *gfP6) *gfP6 {
 | 
				
			||||||
 | 
						e.x.Add(a.x, b.x)
 | 
				
			||||||
 | 
						e.y.Add(a.y, b.y)
 | 
				
			||||||
 | 
						e.z.Add(a.z, b.z)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) Sub(a, b *gfP6) *gfP6 {
 | 
				
			||||||
 | 
						e.x.Sub(a.x, b.x)
 | 
				
			||||||
 | 
						e.y.Sub(a.y, b.y)
 | 
				
			||||||
 | 
						e.z.Sub(a.z, b.z)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) Double(a *gfP6) *gfP6 {
 | 
				
			||||||
 | 
						e.x.Double(a.x)
 | 
				
			||||||
 | 
						e.y.Double(a.y)
 | 
				
			||||||
 | 
						e.z.Double(a.z)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) Mul(a, b *gfP6, pool *bnPool) *gfP6 {
 | 
				
			||||||
 | 
						// "Multiplication and Squaring on Pairing-Friendly Fields"
 | 
				
			||||||
 | 
						// Section 4, Karatsuba method.
 | 
				
			||||||
 | 
						// http://eprint.iacr.org/2006/471.pdf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v0 := newGFp2(pool)
 | 
				
			||||||
 | 
						v0.Mul(a.z, b.z, pool)
 | 
				
			||||||
 | 
						v1 := newGFp2(pool)
 | 
				
			||||||
 | 
						v1.Mul(a.y, b.y, pool)
 | 
				
			||||||
 | 
						v2 := newGFp2(pool)
 | 
				
			||||||
 | 
						v2.Mul(a.x, b.x, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t0 := newGFp2(pool)
 | 
				
			||||||
 | 
						t0.Add(a.x, a.y)
 | 
				
			||||||
 | 
						t1 := newGFp2(pool)
 | 
				
			||||||
 | 
						t1.Add(b.x, b.y)
 | 
				
			||||||
 | 
						tz := newGFp2(pool)
 | 
				
			||||||
 | 
						tz.Mul(t0, t1, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tz.Sub(tz, v1)
 | 
				
			||||||
 | 
						tz.Sub(tz, v2)
 | 
				
			||||||
 | 
						tz.MulXi(tz, pool)
 | 
				
			||||||
 | 
						tz.Add(tz, v0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t0.Add(a.y, a.z)
 | 
				
			||||||
 | 
						t1.Add(b.y, b.z)
 | 
				
			||||||
 | 
						ty := newGFp2(pool)
 | 
				
			||||||
 | 
						ty.Mul(t0, t1, pool)
 | 
				
			||||||
 | 
						ty.Sub(ty, v0)
 | 
				
			||||||
 | 
						ty.Sub(ty, v1)
 | 
				
			||||||
 | 
						t0.MulXi(v2, pool)
 | 
				
			||||||
 | 
						ty.Add(ty, t0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t0.Add(a.x, a.z)
 | 
				
			||||||
 | 
						t1.Add(b.x, b.z)
 | 
				
			||||||
 | 
						tx := newGFp2(pool)
 | 
				
			||||||
 | 
						tx.Mul(t0, t1, pool)
 | 
				
			||||||
 | 
						tx.Sub(tx, v0)
 | 
				
			||||||
 | 
						tx.Add(tx, v1)
 | 
				
			||||||
 | 
						tx.Sub(tx, v2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e.x.Set(tx)
 | 
				
			||||||
 | 
						e.y.Set(ty)
 | 
				
			||||||
 | 
						e.z.Set(tz)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t0.Put(pool)
 | 
				
			||||||
 | 
						t1.Put(pool)
 | 
				
			||||||
 | 
						tx.Put(pool)
 | 
				
			||||||
 | 
						ty.Put(pool)
 | 
				
			||||||
 | 
						tz.Put(pool)
 | 
				
			||||||
 | 
						v0.Put(pool)
 | 
				
			||||||
 | 
						v1.Put(pool)
 | 
				
			||||||
 | 
						v2.Put(pool)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) MulScalar(a *gfP6, b *gfP2, pool *bnPool) *gfP6 {
 | 
				
			||||||
 | 
						e.x.Mul(a.x, b, pool)
 | 
				
			||||||
 | 
						e.y.Mul(a.y, b, pool)
 | 
				
			||||||
 | 
						e.z.Mul(a.z, b, pool)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) MulGFP(a *gfP6, b *big.Int) *gfP6 {
 | 
				
			||||||
 | 
						e.x.MulScalar(a.x, b)
 | 
				
			||||||
 | 
						e.y.MulScalar(a.y, b)
 | 
				
			||||||
 | 
						e.z.MulScalar(a.z, b)
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ
 | 
				
			||||||
 | 
					func (e *gfP6) MulTau(a *gfP6, pool *bnPool) {
 | 
				
			||||||
 | 
						tz := newGFp2(pool)
 | 
				
			||||||
 | 
						tz.MulXi(a.x, pool)
 | 
				
			||||||
 | 
						ty := newGFp2(pool)
 | 
				
			||||||
 | 
						ty.Set(a.y)
 | 
				
			||||||
 | 
						e.y.Set(a.z)
 | 
				
			||||||
 | 
						e.x.Set(ty)
 | 
				
			||||||
 | 
						e.z.Set(tz)
 | 
				
			||||||
 | 
						tz.Put(pool)
 | 
				
			||||||
 | 
						ty.Put(pool)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) Square(a *gfP6, pool *bnPool) *gfP6 {
 | 
				
			||||||
 | 
						v0 := newGFp2(pool).Square(a.z, pool)
 | 
				
			||||||
 | 
						v1 := newGFp2(pool).Square(a.y, pool)
 | 
				
			||||||
 | 
						v2 := newGFp2(pool).Square(a.x, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c0 := newGFp2(pool).Add(a.x, a.y)
 | 
				
			||||||
 | 
						c0.Square(c0, pool)
 | 
				
			||||||
 | 
						c0.Sub(c0, v1)
 | 
				
			||||||
 | 
						c0.Sub(c0, v2)
 | 
				
			||||||
 | 
						c0.MulXi(c0, pool)
 | 
				
			||||||
 | 
						c0.Add(c0, v0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c1 := newGFp2(pool).Add(a.y, a.z)
 | 
				
			||||||
 | 
						c1.Square(c1, pool)
 | 
				
			||||||
 | 
						c1.Sub(c1, v0)
 | 
				
			||||||
 | 
						c1.Sub(c1, v1)
 | 
				
			||||||
 | 
						xiV2 := newGFp2(pool).MulXi(v2, pool)
 | 
				
			||||||
 | 
						c1.Add(c1, xiV2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c2 := newGFp2(pool).Add(a.x, a.z)
 | 
				
			||||||
 | 
						c2.Square(c2, pool)
 | 
				
			||||||
 | 
						c2.Sub(c2, v0)
 | 
				
			||||||
 | 
						c2.Add(c2, v1)
 | 
				
			||||||
 | 
						c2.Sub(c2, v2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e.x.Set(c2)
 | 
				
			||||||
 | 
						e.y.Set(c1)
 | 
				
			||||||
 | 
						e.z.Set(c0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v0.Put(pool)
 | 
				
			||||||
 | 
						v1.Put(pool)
 | 
				
			||||||
 | 
						v2.Put(pool)
 | 
				
			||||||
 | 
						c0.Put(pool)
 | 
				
			||||||
 | 
						c1.Put(pool)
 | 
				
			||||||
 | 
						c2.Put(pool)
 | 
				
			||||||
 | 
						xiV2.Put(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 {
 | 
				
			||||||
 | 
						// See "Implementing cryptographic pairings", M. Scott, section 3.2.
 | 
				
			||||||
 | 
						// ftp://136.206.11.249/pub/crypto/pairings.pdf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Here we can give a short explanation of how it works: let j be a cubic root of
 | 
				
			||||||
 | 
						// unity in GF(p²) so that 1+j+j²=0.
 | 
				
			||||||
 | 
						// Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
 | 
				
			||||||
 | 
						// = (xτ² + yτ + z)(Cτ²+Bτ+A)
 | 
				
			||||||
 | 
						// = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm).
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
 | 
				
			||||||
 | 
						// = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy)
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz)
 | 
				
			||||||
 | 
						t1 := newGFp2(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						A := newGFp2(pool)
 | 
				
			||||||
 | 
						A.Square(a.z, pool)
 | 
				
			||||||
 | 
						t1.Mul(a.x, a.y, pool)
 | 
				
			||||||
 | 
						t1.MulXi(t1, pool)
 | 
				
			||||||
 | 
						A.Sub(A, t1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						B := newGFp2(pool)
 | 
				
			||||||
 | 
						B.Square(a.x, pool)
 | 
				
			||||||
 | 
						B.MulXi(B, pool)
 | 
				
			||||||
 | 
						t1.Mul(a.y, a.z, pool)
 | 
				
			||||||
 | 
						B.Sub(B, t1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						C := newGFp2(pool)
 | 
				
			||||||
 | 
						C.Square(a.y, pool)
 | 
				
			||||||
 | 
						t1.Mul(a.x, a.z, pool)
 | 
				
			||||||
 | 
						C.Sub(C, t1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						F := newGFp2(pool)
 | 
				
			||||||
 | 
						F.Mul(C, a.y, pool)
 | 
				
			||||||
 | 
						F.MulXi(F, pool)
 | 
				
			||||||
 | 
						t1.Mul(A, a.z, pool)
 | 
				
			||||||
 | 
						F.Add(F, t1)
 | 
				
			||||||
 | 
						t1.Mul(B, a.x, pool)
 | 
				
			||||||
 | 
						t1.MulXi(t1, pool)
 | 
				
			||||||
 | 
						F.Add(F, t1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						F.Invert(F, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e.x.Mul(C, F, pool)
 | 
				
			||||||
 | 
						e.y.Mul(B, F, pool)
 | 
				
			||||||
 | 
						e.z.Mul(A, F, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t1.Put(pool)
 | 
				
			||||||
 | 
						A.Put(pool)
 | 
				
			||||||
 | 
						B.Put(pool)
 | 
				
			||||||
 | 
						C.Put(pool)
 | 
				
			||||||
 | 
						F.Put(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										71
									
								
								crypto/bn256/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								crypto/bn256/main_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
				
			|||||||
 | 
					package bn256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"crypto/rand"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestRandomG2Marshal(t *testing.T) {
 | 
				
			||||||
 | 
						for i := 0; i < 10; i++ {
 | 
				
			||||||
 | 
							n, g2, err := RandomG2(rand.Reader)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Error(err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							t.Logf("%d: %x\n", n, g2.Marshal())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestPairings(t *testing.T) {
 | 
				
			||||||
 | 
						a1 := new(G1).ScalarBaseMult(bigFromBase10("1"))
 | 
				
			||||||
 | 
						a2 := new(G1).ScalarBaseMult(bigFromBase10("2"))
 | 
				
			||||||
 | 
						a37 := new(G1).ScalarBaseMult(bigFromBase10("37"))
 | 
				
			||||||
 | 
						an1 := new(G1).ScalarBaseMult(bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495616"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						b0 := new(G2).ScalarBaseMult(bigFromBase10("0"))
 | 
				
			||||||
 | 
						b1 := new(G2).ScalarBaseMult(bigFromBase10("1"))
 | 
				
			||||||
 | 
						b2 := new(G2).ScalarBaseMult(bigFromBase10("2"))
 | 
				
			||||||
 | 
						b27 := new(G2).ScalarBaseMult(bigFromBase10("27"))
 | 
				
			||||||
 | 
						b999 := new(G2).ScalarBaseMult(bigFromBase10("999"))
 | 
				
			||||||
 | 
						bn1 := new(G2).ScalarBaseMult(bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495616"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p1 := Pair(a1, b1)
 | 
				
			||||||
 | 
						pn1 := Pair(a1, bn1)
 | 
				
			||||||
 | 
						np1 := Pair(an1, b1)
 | 
				
			||||||
 | 
						if pn1.String() != np1.String() {
 | 
				
			||||||
 | 
							t.Error("Pairing mismatch: e(a, -b) != e(-a, b)")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !PairingCheck([]*G1{a1, an1}, []*G2{b1, b1}) {
 | 
				
			||||||
 | 
							t.Error("MultiAte check gave false negative!")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p0 := new(GT).Add(p1, pn1)
 | 
				
			||||||
 | 
						p0_2 := Pair(a1, b0)
 | 
				
			||||||
 | 
						if p0.String() != p0_2.String() {
 | 
				
			||||||
 | 
							t.Error("Pairing mismatch: e(a, b) * e(a, -b) != 1")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p0_3 := new(GT).ScalarMult(p1, bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617"))
 | 
				
			||||||
 | 
						if p0.String() != p0_3.String() {
 | 
				
			||||||
 | 
							t.Error("Pairing mismatch: e(a, b) has wrong order")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p2 := Pair(a2, b1)
 | 
				
			||||||
 | 
						p2_2 := Pair(a1, b2)
 | 
				
			||||||
 | 
						p2_3 := new(GT).ScalarMult(p1, bigFromBase10("2"))
 | 
				
			||||||
 | 
						if p2.String() != p2_2.String() {
 | 
				
			||||||
 | 
							t.Error("Pairing mismatch: e(a, b * 2) != e(a * 2, b)")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if p2.String() != p2_3.String() {
 | 
				
			||||||
 | 
							t.Error("Pairing mismatch: e(a, b * 2) != e(a, b) ** 2")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if p2.String() == p1.String() {
 | 
				
			||||||
 | 
							t.Error("Pairing is degenerate!")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if PairingCheck([]*G1{a1, a1}, []*G2{b1, b1}) {
 | 
				
			||||||
 | 
							t.Error("MultiAte check gave false positive!")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p999 := Pair(a37, b27)
 | 
				
			||||||
 | 
						p999_2 := Pair(a1, b999)
 | 
				
			||||||
 | 
						if p999.String() != p999_2.String() {
 | 
				
			||||||
 | 
							t.Error("Pairing mismatch: e(a * 37, b * 27) != e(a, b * 999)")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										398
									
								
								crypto/bn256/optate.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										398
									
								
								crypto/bn256/optate.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,398 @@
 | 
				
			|||||||
 | 
					// Copyright 2012 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package bn256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) {
 | 
				
			||||||
 | 
						// See the mixed addition algorithm from "Faster Computation of the
 | 
				
			||||||
 | 
						// Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						B := newGFp2(pool).Mul(p.x, r.t, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						D := newGFp2(pool).Add(p.y, r.z)
 | 
				
			||||||
 | 
						D.Square(D, pool)
 | 
				
			||||||
 | 
						D.Sub(D, r2)
 | 
				
			||||||
 | 
						D.Sub(D, r.t)
 | 
				
			||||||
 | 
						D.Mul(D, r.t, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						H := newGFp2(pool).Sub(B, r.x)
 | 
				
			||||||
 | 
						I := newGFp2(pool).Square(H, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						E := newGFp2(pool).Add(I, I)
 | 
				
			||||||
 | 
						E.Add(E, E)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						J := newGFp2(pool).Mul(H, E, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						L1 := newGFp2(pool).Sub(D, r.y)
 | 
				
			||||||
 | 
						L1.Sub(L1, r.y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						V := newGFp2(pool).Mul(r.x, E, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rOut = newTwistPoint(pool)
 | 
				
			||||||
 | 
						rOut.x.Square(L1, pool)
 | 
				
			||||||
 | 
						rOut.x.Sub(rOut.x, J)
 | 
				
			||||||
 | 
						rOut.x.Sub(rOut.x, V)
 | 
				
			||||||
 | 
						rOut.x.Sub(rOut.x, V)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rOut.z.Add(r.z, H)
 | 
				
			||||||
 | 
						rOut.z.Square(rOut.z, pool)
 | 
				
			||||||
 | 
						rOut.z.Sub(rOut.z, r.t)
 | 
				
			||||||
 | 
						rOut.z.Sub(rOut.z, I)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t := newGFp2(pool).Sub(V, rOut.x)
 | 
				
			||||||
 | 
						t.Mul(t, L1, pool)
 | 
				
			||||||
 | 
						t2 := newGFp2(pool).Mul(r.y, J, pool)
 | 
				
			||||||
 | 
						t2.Add(t2, t2)
 | 
				
			||||||
 | 
						rOut.y.Sub(t, t2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rOut.t.Square(rOut.z, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Add(p.y, rOut.z)
 | 
				
			||||||
 | 
						t.Square(t, pool)
 | 
				
			||||||
 | 
						t.Sub(t, r2)
 | 
				
			||||||
 | 
						t.Sub(t, rOut.t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t2.Mul(L1, p.x, pool)
 | 
				
			||||||
 | 
						t2.Add(t2, t2)
 | 
				
			||||||
 | 
						a = newGFp2(pool)
 | 
				
			||||||
 | 
						a.Sub(t2, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c = newGFp2(pool)
 | 
				
			||||||
 | 
						c.MulScalar(rOut.z, q.y)
 | 
				
			||||||
 | 
						c.Add(c, c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						b = newGFp2(pool)
 | 
				
			||||||
 | 
						b.SetZero()
 | 
				
			||||||
 | 
						b.Sub(b, L1)
 | 
				
			||||||
 | 
						b.MulScalar(b, q.x)
 | 
				
			||||||
 | 
						b.Add(b, b)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						B.Put(pool)
 | 
				
			||||||
 | 
						D.Put(pool)
 | 
				
			||||||
 | 
						H.Put(pool)
 | 
				
			||||||
 | 
						I.Put(pool)
 | 
				
			||||||
 | 
						E.Put(pool)
 | 
				
			||||||
 | 
						J.Put(pool)
 | 
				
			||||||
 | 
						L1.Put(pool)
 | 
				
			||||||
 | 
						V.Put(pool)
 | 
				
			||||||
 | 
						t.Put(pool)
 | 
				
			||||||
 | 
						t2.Put(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) {
 | 
				
			||||||
 | 
						// See the doubling algorithm for a=0 from "Faster Computation of the
 | 
				
			||||||
 | 
						// Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						A := newGFp2(pool).Square(r.x, pool)
 | 
				
			||||||
 | 
						B := newGFp2(pool).Square(r.y, pool)
 | 
				
			||||||
 | 
						C := newGFp2(pool).Square(B, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						D := newGFp2(pool).Add(r.x, B)
 | 
				
			||||||
 | 
						D.Square(D, pool)
 | 
				
			||||||
 | 
						D.Sub(D, A)
 | 
				
			||||||
 | 
						D.Sub(D, C)
 | 
				
			||||||
 | 
						D.Add(D, D)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						E := newGFp2(pool).Add(A, A)
 | 
				
			||||||
 | 
						E.Add(E, A)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						G := newGFp2(pool).Square(E, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rOut = newTwistPoint(pool)
 | 
				
			||||||
 | 
						rOut.x.Sub(G, D)
 | 
				
			||||||
 | 
						rOut.x.Sub(rOut.x, D)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rOut.z.Add(r.y, r.z)
 | 
				
			||||||
 | 
						rOut.z.Square(rOut.z, pool)
 | 
				
			||||||
 | 
						rOut.z.Sub(rOut.z, B)
 | 
				
			||||||
 | 
						rOut.z.Sub(rOut.z, r.t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rOut.y.Sub(D, rOut.x)
 | 
				
			||||||
 | 
						rOut.y.Mul(rOut.y, E, pool)
 | 
				
			||||||
 | 
						t := newGFp2(pool).Add(C, C)
 | 
				
			||||||
 | 
						t.Add(t, t)
 | 
				
			||||||
 | 
						t.Add(t, t)
 | 
				
			||||||
 | 
						rOut.y.Sub(rOut.y, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rOut.t.Square(rOut.z, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Mul(E, r.t, pool)
 | 
				
			||||||
 | 
						t.Add(t, t)
 | 
				
			||||||
 | 
						b = newGFp2(pool)
 | 
				
			||||||
 | 
						b.SetZero()
 | 
				
			||||||
 | 
						b.Sub(b, t)
 | 
				
			||||||
 | 
						b.MulScalar(b, q.x)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						a = newGFp2(pool)
 | 
				
			||||||
 | 
						a.Add(r.x, E)
 | 
				
			||||||
 | 
						a.Square(a, pool)
 | 
				
			||||||
 | 
						a.Sub(a, A)
 | 
				
			||||||
 | 
						a.Sub(a, G)
 | 
				
			||||||
 | 
						t.Add(B, B)
 | 
				
			||||||
 | 
						t.Add(t, t)
 | 
				
			||||||
 | 
						a.Sub(a, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c = newGFp2(pool)
 | 
				
			||||||
 | 
						c.Mul(rOut.z, r.t, pool)
 | 
				
			||||||
 | 
						c.Add(c, c)
 | 
				
			||||||
 | 
						c.MulScalar(c, q.y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						A.Put(pool)
 | 
				
			||||||
 | 
						B.Put(pool)
 | 
				
			||||||
 | 
						C.Put(pool)
 | 
				
			||||||
 | 
						D.Put(pool)
 | 
				
			||||||
 | 
						E.Put(pool)
 | 
				
			||||||
 | 
						G.Put(pool)
 | 
				
			||||||
 | 
						t.Put(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func mulLine(ret *gfP12, a, b, c *gfP2, pool *bnPool) {
 | 
				
			||||||
 | 
						a2 := newGFp6(pool)
 | 
				
			||||||
 | 
						a2.x.SetZero()
 | 
				
			||||||
 | 
						a2.y.Set(a)
 | 
				
			||||||
 | 
						a2.z.Set(b)
 | 
				
			||||||
 | 
						a2.Mul(a2, ret.x, pool)
 | 
				
			||||||
 | 
						t3 := newGFp6(pool).MulScalar(ret.y, c, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t := newGFp2(pool)
 | 
				
			||||||
 | 
						t.Add(b, c)
 | 
				
			||||||
 | 
						t2 := newGFp6(pool)
 | 
				
			||||||
 | 
						t2.x.SetZero()
 | 
				
			||||||
 | 
						t2.y.Set(a)
 | 
				
			||||||
 | 
						t2.z.Set(t)
 | 
				
			||||||
 | 
						ret.x.Add(ret.x, ret.y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret.y.Set(t3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret.x.Mul(ret.x, t2, pool)
 | 
				
			||||||
 | 
						ret.x.Sub(ret.x, a2)
 | 
				
			||||||
 | 
						ret.x.Sub(ret.x, ret.y)
 | 
				
			||||||
 | 
						a2.MulTau(a2, pool)
 | 
				
			||||||
 | 
						ret.y.Add(ret.y, a2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						a2.Put(pool)
 | 
				
			||||||
 | 
						t3.Put(pool)
 | 
				
			||||||
 | 
						t2.Put(pool)
 | 
				
			||||||
 | 
						t.Put(pool)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// sixuPlus2NAF is 6u+2 in non-adjacent form.
 | 
				
			||||||
 | 
					var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 1, -1, 0, 0, 1, 0,
 | 
				
			||||||
 | 
						0, 1, 1, 0, -1, 0, 0, 1, 0, -1, 0, 0, 0, 0, 1, 1,
 | 
				
			||||||
 | 
						1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1,
 | 
				
			||||||
 | 
						1, 0, 0, -1, 0, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0, 1, 1}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// miller implements the Miller loop for calculating the Optimal Ate pairing.
 | 
				
			||||||
 | 
					// See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf
 | 
				
			||||||
 | 
					func miller(q *twistPoint, p *curvePoint, pool *bnPool) *gfP12 {
 | 
				
			||||||
 | 
						ret := newGFp12(pool)
 | 
				
			||||||
 | 
						ret.SetOne()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						aAffine := newTwistPoint(pool)
 | 
				
			||||||
 | 
						aAffine.Set(q)
 | 
				
			||||||
 | 
						aAffine.MakeAffine(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bAffine := newCurvePoint(pool)
 | 
				
			||||||
 | 
						bAffine.Set(p)
 | 
				
			||||||
 | 
						bAffine.MakeAffine(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						minusA := newTwistPoint(pool)
 | 
				
			||||||
 | 
						minusA.Negative(aAffine, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r := newTwistPoint(pool)
 | 
				
			||||||
 | 
						r.Set(aAffine)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r2 := newGFp2(pool)
 | 
				
			||||||
 | 
						r2.Square(aAffine.y, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := len(sixuPlus2NAF) - 1; i > 0; i-- {
 | 
				
			||||||
 | 
							a, b, c, newR := lineFunctionDouble(r, bAffine, pool)
 | 
				
			||||||
 | 
							if i != len(sixuPlus2NAF)-1 {
 | 
				
			||||||
 | 
								ret.Square(ret, pool)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mulLine(ret, a, b, c, pool)
 | 
				
			||||||
 | 
							a.Put(pool)
 | 
				
			||||||
 | 
							b.Put(pool)
 | 
				
			||||||
 | 
							c.Put(pool)
 | 
				
			||||||
 | 
							r.Put(pool)
 | 
				
			||||||
 | 
							r = newR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch sixuPlus2NAF[i-1] {
 | 
				
			||||||
 | 
							case 1:
 | 
				
			||||||
 | 
								a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2, pool)
 | 
				
			||||||
 | 
							case -1:
 | 
				
			||||||
 | 
								a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2, pool)
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mulLine(ret, a, b, c, pool)
 | 
				
			||||||
 | 
							a.Put(pool)
 | 
				
			||||||
 | 
							b.Put(pool)
 | 
				
			||||||
 | 
							c.Put(pool)
 | 
				
			||||||
 | 
							r.Put(pool)
 | 
				
			||||||
 | 
							r = newR
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// In order to calculate Q1 we have to convert q from the sextic twist
 | 
				
			||||||
 | 
						// to the full GF(p^12) group, apply the Frobenius there, and convert
 | 
				
			||||||
 | 
						// back.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// The twist isomorphism is (x', y') -> (xω², yω³). If we consider just
 | 
				
			||||||
 | 
						// x for a moment, then after applying the Frobenius, we have x̄ω^(2p)
 | 
				
			||||||
 | 
						// where x̄ is the conjugate of x. If we are going to apply the inverse
 | 
				
			||||||
 | 
						// isomorphism we need a value with a single coefficient of ω² so we
 | 
				
			||||||
 | 
						// rewrite this as x̄ω^(2p-2)ω². ξ⁶ = ω and, due to the construction of
 | 
				
			||||||
 | 
						// p, 2p-2 is a multiple of six. Therefore we can rewrite as
 | 
				
			||||||
 | 
						// x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the
 | 
				
			||||||
 | 
						// ω².
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// A similar argument can be made for the y value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						q1 := newTwistPoint(pool)
 | 
				
			||||||
 | 
						q1.x.Conjugate(aAffine.x)
 | 
				
			||||||
 | 
						q1.x.Mul(q1.x, xiToPMinus1Over3, pool)
 | 
				
			||||||
 | 
						q1.y.Conjugate(aAffine.y)
 | 
				
			||||||
 | 
						q1.y.Mul(q1.y, xiToPMinus1Over2, pool)
 | 
				
			||||||
 | 
						q1.z.SetOne()
 | 
				
			||||||
 | 
						q1.t.SetOne()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// For Q2 we are applying the p² Frobenius. The two conjugations cancel
 | 
				
			||||||
 | 
						// out and we are left only with the factors from the isomorphism. In
 | 
				
			||||||
 | 
						// the case of x, we end up with a pure number which is why
 | 
				
			||||||
 | 
						// xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We
 | 
				
			||||||
 | 
						// ignore this to end up with -Q2.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						minusQ2 := newTwistPoint(pool)
 | 
				
			||||||
 | 
						minusQ2.x.MulScalar(aAffine.x, xiToPSquaredMinus1Over3)
 | 
				
			||||||
 | 
						minusQ2.y.Set(aAffine.y)
 | 
				
			||||||
 | 
						minusQ2.z.SetOne()
 | 
				
			||||||
 | 
						minusQ2.t.SetOne()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r2.Square(q1.y, pool)
 | 
				
			||||||
 | 
						a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2, pool)
 | 
				
			||||||
 | 
						mulLine(ret, a, b, c, pool)
 | 
				
			||||||
 | 
						a.Put(pool)
 | 
				
			||||||
 | 
						b.Put(pool)
 | 
				
			||||||
 | 
						c.Put(pool)
 | 
				
			||||||
 | 
						r.Put(pool)
 | 
				
			||||||
 | 
						r = newR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r2.Square(minusQ2.y, pool)
 | 
				
			||||||
 | 
						a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2, pool)
 | 
				
			||||||
 | 
						mulLine(ret, a, b, c, pool)
 | 
				
			||||||
 | 
						a.Put(pool)
 | 
				
			||||||
 | 
						b.Put(pool)
 | 
				
			||||||
 | 
						c.Put(pool)
 | 
				
			||||||
 | 
						r.Put(pool)
 | 
				
			||||||
 | 
						r = newR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						aAffine.Put(pool)
 | 
				
			||||||
 | 
						bAffine.Put(pool)
 | 
				
			||||||
 | 
						minusA.Put(pool)
 | 
				
			||||||
 | 
						r.Put(pool)
 | 
				
			||||||
 | 
						r2.Put(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// finalExponentiation computes the (p¹²-1)/Order-th power of an element of
 | 
				
			||||||
 | 
					// GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from
 | 
				
			||||||
 | 
					// http://cryptojedi.org/papers/dclxvi-20100714.pdf)
 | 
				
			||||||
 | 
					func finalExponentiation(in *gfP12, pool *bnPool) *gfP12 {
 | 
				
			||||||
 | 
						t1 := newGFp12(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// This is the p^6-Frobenius
 | 
				
			||||||
 | 
						t1.x.Negative(in.x)
 | 
				
			||||||
 | 
						t1.y.Set(in.y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inv := newGFp12(pool)
 | 
				
			||||||
 | 
						inv.Invert(in, pool)
 | 
				
			||||||
 | 
						t1.Mul(t1, inv, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t2 := newGFp12(pool).FrobeniusP2(t1, pool)
 | 
				
			||||||
 | 
						t1.Mul(t1, t2, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fp := newGFp12(pool).Frobenius(t1, pool)
 | 
				
			||||||
 | 
						fp2 := newGFp12(pool).FrobeniusP2(t1, pool)
 | 
				
			||||||
 | 
						fp3 := newGFp12(pool).Frobenius(fp2, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fu, fu2, fu3 := newGFp12(pool), newGFp12(pool), newGFp12(pool)
 | 
				
			||||||
 | 
						fu.Exp(t1, u, pool)
 | 
				
			||||||
 | 
						fu2.Exp(fu, u, pool)
 | 
				
			||||||
 | 
						fu3.Exp(fu2, u, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						y3 := newGFp12(pool).Frobenius(fu, pool)
 | 
				
			||||||
 | 
						fu2p := newGFp12(pool).Frobenius(fu2, pool)
 | 
				
			||||||
 | 
						fu3p := newGFp12(pool).Frobenius(fu3, pool)
 | 
				
			||||||
 | 
						y2 := newGFp12(pool).FrobeniusP2(fu2, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						y0 := newGFp12(pool)
 | 
				
			||||||
 | 
						y0.Mul(fp, fp2, pool)
 | 
				
			||||||
 | 
						y0.Mul(y0, fp3, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						y1, y4, y5 := newGFp12(pool), newGFp12(pool), newGFp12(pool)
 | 
				
			||||||
 | 
						y1.Conjugate(t1)
 | 
				
			||||||
 | 
						y5.Conjugate(fu2)
 | 
				
			||||||
 | 
						y3.Conjugate(y3)
 | 
				
			||||||
 | 
						y4.Mul(fu, fu2p, pool)
 | 
				
			||||||
 | 
						y4.Conjugate(y4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						y6 := newGFp12(pool)
 | 
				
			||||||
 | 
						y6.Mul(fu3, fu3p, pool)
 | 
				
			||||||
 | 
						y6.Conjugate(y6)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t0 := newGFp12(pool)
 | 
				
			||||||
 | 
						t0.Square(y6, pool)
 | 
				
			||||||
 | 
						t0.Mul(t0, y4, pool)
 | 
				
			||||||
 | 
						t0.Mul(t0, y5, pool)
 | 
				
			||||||
 | 
						t1.Mul(y3, y5, pool)
 | 
				
			||||||
 | 
						t1.Mul(t1, t0, pool)
 | 
				
			||||||
 | 
						t0.Mul(t0, y2, pool)
 | 
				
			||||||
 | 
						t1.Square(t1, pool)
 | 
				
			||||||
 | 
						t1.Mul(t1, t0, pool)
 | 
				
			||||||
 | 
						t1.Square(t1, pool)
 | 
				
			||||||
 | 
						t0.Mul(t1, y1, pool)
 | 
				
			||||||
 | 
						t1.Mul(t1, y0, pool)
 | 
				
			||||||
 | 
						t0.Square(t0, pool)
 | 
				
			||||||
 | 
						t0.Mul(t0, t1, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inv.Put(pool)
 | 
				
			||||||
 | 
						t1.Put(pool)
 | 
				
			||||||
 | 
						t2.Put(pool)
 | 
				
			||||||
 | 
						fp.Put(pool)
 | 
				
			||||||
 | 
						fp2.Put(pool)
 | 
				
			||||||
 | 
						fp3.Put(pool)
 | 
				
			||||||
 | 
						fu.Put(pool)
 | 
				
			||||||
 | 
						fu2.Put(pool)
 | 
				
			||||||
 | 
						fu3.Put(pool)
 | 
				
			||||||
 | 
						fu2p.Put(pool)
 | 
				
			||||||
 | 
						fu3p.Put(pool)
 | 
				
			||||||
 | 
						y0.Put(pool)
 | 
				
			||||||
 | 
						y1.Put(pool)
 | 
				
			||||||
 | 
						y2.Put(pool)
 | 
				
			||||||
 | 
						y3.Put(pool)
 | 
				
			||||||
 | 
						y4.Put(pool)
 | 
				
			||||||
 | 
						y5.Put(pool)
 | 
				
			||||||
 | 
						y6.Put(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return t0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func optimalAte(a *twistPoint, b *curvePoint, pool *bnPool) *gfP12 {
 | 
				
			||||||
 | 
						e := miller(a, b, pool)
 | 
				
			||||||
 | 
						ret := finalExponentiation(e, pool)
 | 
				
			||||||
 | 
						e.Put(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if a.IsInfinity() || b.IsInfinity() {
 | 
				
			||||||
 | 
							ret.SetOne()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										249
									
								
								crypto/bn256/twist.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								crypto/bn256/twist.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,249 @@
 | 
				
			|||||||
 | 
					// Copyright 2012 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package bn256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are
 | 
				
			||||||
 | 
					// kept in Jacobian form and t=z² when valid. The group G₂ is the set of
 | 
				
			||||||
 | 
					// n-torsion points of this curve over GF(p²) (where n = Order)
 | 
				
			||||||
 | 
					type twistPoint struct {
 | 
				
			||||||
 | 
						x, y, z, t *gfP2
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var twistB = &gfP2{
 | 
				
			||||||
 | 
						bigFromBase10("266929791119991161246907387137283842545076965332900288569378510910307636690"),
 | 
				
			||||||
 | 
						bigFromBase10("19485874751759354771024239261021720505790618469301721065564631296452457478373"),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// twistGen is the generator of group G₂.
 | 
				
			||||||
 | 
					var twistGen = &twistPoint{
 | 
				
			||||||
 | 
						&gfP2{
 | 
				
			||||||
 | 
							bigFromBase10("11559732032986387107991004021392285783925812861821192530917403151452391805634"),
 | 
				
			||||||
 | 
							bigFromBase10("10857046999023057135944570762232829481370756359578518086990519993285655852781"),
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						&gfP2{
 | 
				
			||||||
 | 
							bigFromBase10("4082367875863433681332203403145435568316851327593401208105741076214120093531"),
 | 
				
			||||||
 | 
							bigFromBase10("8495653923123431417604973247489272438418190587263600148770280649306958101930"),
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						&gfP2{
 | 
				
			||||||
 | 
							bigFromBase10("0"),
 | 
				
			||||||
 | 
							bigFromBase10("1"),
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						&gfP2{
 | 
				
			||||||
 | 
							bigFromBase10("0"),
 | 
				
			||||||
 | 
							bigFromBase10("1"),
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newTwistPoint(pool *bnPool) *twistPoint {
 | 
				
			||||||
 | 
						return &twistPoint{
 | 
				
			||||||
 | 
							newGFp2(pool),
 | 
				
			||||||
 | 
							newGFp2(pool),
 | 
				
			||||||
 | 
							newGFp2(pool),
 | 
				
			||||||
 | 
							newGFp2(pool),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *twistPoint) String() string {
 | 
				
			||||||
 | 
						return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *twistPoint) Put(pool *bnPool) {
 | 
				
			||||||
 | 
						c.x.Put(pool)
 | 
				
			||||||
 | 
						c.y.Put(pool)
 | 
				
			||||||
 | 
						c.z.Put(pool)
 | 
				
			||||||
 | 
						c.t.Put(pool)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *twistPoint) Set(a *twistPoint) {
 | 
				
			||||||
 | 
						c.x.Set(a.x)
 | 
				
			||||||
 | 
						c.y.Set(a.y)
 | 
				
			||||||
 | 
						c.z.Set(a.z)
 | 
				
			||||||
 | 
						c.t.Set(a.t)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsOnCurve returns true iff c is on the curve where c must be in affine form.
 | 
				
			||||||
 | 
					func (c *twistPoint) IsOnCurve() bool {
 | 
				
			||||||
 | 
						pool := new(bnPool)
 | 
				
			||||||
 | 
						yy := newGFp2(pool).Square(c.y, pool)
 | 
				
			||||||
 | 
						xxx := newGFp2(pool).Square(c.x, pool)
 | 
				
			||||||
 | 
						xxx.Mul(xxx, c.x, pool)
 | 
				
			||||||
 | 
						yy.Sub(yy, xxx)
 | 
				
			||||||
 | 
						yy.Sub(yy, twistB)
 | 
				
			||||||
 | 
						yy.Minimal()
 | 
				
			||||||
 | 
						return yy.x.Sign() == 0 && yy.y.Sign() == 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *twistPoint) SetInfinity() {
 | 
				
			||||||
 | 
						c.z.SetZero()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *twistPoint) IsInfinity() bool {
 | 
				
			||||||
 | 
						return c.z.IsZero()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) {
 | 
				
			||||||
 | 
						// For additional comments, see the same function in curve.go.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if a.IsInfinity() {
 | 
				
			||||||
 | 
							c.Set(b)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if b.IsInfinity() {
 | 
				
			||||||
 | 
							c.Set(a)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
 | 
				
			||||||
 | 
						z1z1 := newGFp2(pool).Square(a.z, pool)
 | 
				
			||||||
 | 
						z2z2 := newGFp2(pool).Square(b.z, pool)
 | 
				
			||||||
 | 
						u1 := newGFp2(pool).Mul(a.x, z2z2, pool)
 | 
				
			||||||
 | 
						u2 := newGFp2(pool).Mul(b.x, z1z1, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t := newGFp2(pool).Mul(b.z, z2z2, pool)
 | 
				
			||||||
 | 
						s1 := newGFp2(pool).Mul(a.y, t, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Mul(a.z, z1z1, pool)
 | 
				
			||||||
 | 
						s2 := newGFp2(pool).Mul(b.y, t, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h := newGFp2(pool).Sub(u2, u1)
 | 
				
			||||||
 | 
						xEqual := h.IsZero()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Add(h, h)
 | 
				
			||||||
 | 
						i := newGFp2(pool).Square(t, pool)
 | 
				
			||||||
 | 
						j := newGFp2(pool).Mul(h, i, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Sub(s2, s1)
 | 
				
			||||||
 | 
						yEqual := t.IsZero()
 | 
				
			||||||
 | 
						if xEqual && yEqual {
 | 
				
			||||||
 | 
							c.Double(a, pool)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						r := newGFp2(pool).Add(t, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v := newGFp2(pool).Mul(u1, i, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t4 := newGFp2(pool).Square(r, pool)
 | 
				
			||||||
 | 
						t.Add(v, v)
 | 
				
			||||||
 | 
						t6 := newGFp2(pool).Sub(t4, j)
 | 
				
			||||||
 | 
						c.x.Sub(t6, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Sub(v, c.x)       // t7
 | 
				
			||||||
 | 
						t4.Mul(s1, j, pool) // t8
 | 
				
			||||||
 | 
						t6.Add(t4, t4)      // t9
 | 
				
			||||||
 | 
						t4.Mul(r, t, pool)  // t10
 | 
				
			||||||
 | 
						c.y.Sub(t4, t6)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Add(a.z, b.z)    // t11
 | 
				
			||||||
 | 
						t4.Square(t, pool) // t12
 | 
				
			||||||
 | 
						t.Sub(t4, z1z1)    // t13
 | 
				
			||||||
 | 
						t4.Sub(t, z2z2)    // t14
 | 
				
			||||||
 | 
						c.z.Mul(t4, h, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						z1z1.Put(pool)
 | 
				
			||||||
 | 
						z2z2.Put(pool)
 | 
				
			||||||
 | 
						u1.Put(pool)
 | 
				
			||||||
 | 
						u2.Put(pool)
 | 
				
			||||||
 | 
						t.Put(pool)
 | 
				
			||||||
 | 
						s1.Put(pool)
 | 
				
			||||||
 | 
						s2.Put(pool)
 | 
				
			||||||
 | 
						h.Put(pool)
 | 
				
			||||||
 | 
						i.Put(pool)
 | 
				
			||||||
 | 
						j.Put(pool)
 | 
				
			||||||
 | 
						r.Put(pool)
 | 
				
			||||||
 | 
						v.Put(pool)
 | 
				
			||||||
 | 
						t4.Put(pool)
 | 
				
			||||||
 | 
						t6.Put(pool)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *twistPoint) Double(a *twistPoint, pool *bnPool) {
 | 
				
			||||||
 | 
						// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
 | 
				
			||||||
 | 
						A := newGFp2(pool).Square(a.x, pool)
 | 
				
			||||||
 | 
						B := newGFp2(pool).Square(a.y, pool)
 | 
				
			||||||
 | 
						C := newGFp2(pool).Square(B, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t := newGFp2(pool).Add(a.x, B)
 | 
				
			||||||
 | 
						t2 := newGFp2(pool).Square(t, pool)
 | 
				
			||||||
 | 
						t.Sub(t2, A)
 | 
				
			||||||
 | 
						t2.Sub(t, C)
 | 
				
			||||||
 | 
						d := newGFp2(pool).Add(t2, t2)
 | 
				
			||||||
 | 
						t.Add(A, A)
 | 
				
			||||||
 | 
						e := newGFp2(pool).Add(t, A)
 | 
				
			||||||
 | 
						f := newGFp2(pool).Square(e, pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Add(d, d)
 | 
				
			||||||
 | 
						c.x.Sub(f, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Add(C, C)
 | 
				
			||||||
 | 
						t2.Add(t, t)
 | 
				
			||||||
 | 
						t.Add(t2, t2)
 | 
				
			||||||
 | 
						c.y.Sub(d, c.x)
 | 
				
			||||||
 | 
						t2.Mul(e, c.y, pool)
 | 
				
			||||||
 | 
						c.y.Sub(t2, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Mul(a.y, a.z, pool)
 | 
				
			||||||
 | 
						c.z.Add(t, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						A.Put(pool)
 | 
				
			||||||
 | 
						B.Put(pool)
 | 
				
			||||||
 | 
						C.Put(pool)
 | 
				
			||||||
 | 
						t.Put(pool)
 | 
				
			||||||
 | 
						t2.Put(pool)
 | 
				
			||||||
 | 
						d.Put(pool)
 | 
				
			||||||
 | 
						e.Put(pool)
 | 
				
			||||||
 | 
						f.Put(pool)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint {
 | 
				
			||||||
 | 
						sum := newTwistPoint(pool)
 | 
				
			||||||
 | 
						sum.SetInfinity()
 | 
				
			||||||
 | 
						t := newTwistPoint(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := scalar.BitLen(); i >= 0; i-- {
 | 
				
			||||||
 | 
							t.Double(sum, pool)
 | 
				
			||||||
 | 
							if scalar.Bit(i) != 0 {
 | 
				
			||||||
 | 
								sum.Add(t, a, pool)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								sum.Set(t)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c.Set(sum)
 | 
				
			||||||
 | 
						sum.Put(pool)
 | 
				
			||||||
 | 
						t.Put(pool)
 | 
				
			||||||
 | 
						return c
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint {
 | 
				
			||||||
 | 
						if c.z.IsOne() {
 | 
				
			||||||
 | 
							return c
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						zInv := newGFp2(pool).Invert(c.z, pool)
 | 
				
			||||||
 | 
						t := newGFp2(pool).Mul(c.y, zInv, pool)
 | 
				
			||||||
 | 
						zInv2 := newGFp2(pool).Square(zInv, pool)
 | 
				
			||||||
 | 
						c.y.Mul(t, zInv2, pool)
 | 
				
			||||||
 | 
						t.Mul(c.x, zInv2, pool)
 | 
				
			||||||
 | 
						c.x.Set(t)
 | 
				
			||||||
 | 
						c.z.SetOne()
 | 
				
			||||||
 | 
						c.t.SetOne()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						zInv.Put(pool)
 | 
				
			||||||
 | 
						t.Put(pool)
 | 
				
			||||||
 | 
						zInv2.Put(pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return c
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) {
 | 
				
			||||||
 | 
						c.x.Set(a.x)
 | 
				
			||||||
 | 
						c.y.SetZero()
 | 
				
			||||||
 | 
						c.y.Sub(c.y, a.y)
 | 
				
			||||||
 | 
						c.z.Set(a.z)
 | 
				
			||||||
 | 
						c.t.SetZero()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -48,7 +48,7 @@ func runTrace(tracer *JavascriptTracer) (interface{}, error) {
 | 
				
			|||||||
	contract := vm.NewContract(account{}, account{}, big.NewInt(0), 10000)
 | 
						contract := vm.NewContract(account{}, account{}, big.NewInt(0), 10000)
 | 
				
			||||||
	contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
 | 
						contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err := env.Interpreter().Run(contract, []byte{})
 | 
						_, err := env.Interpreter().Run(0, contract, []byte{})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -523,7 +523,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB
 | 
				
			|||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// Start executing the transaction
 | 
							// Start executing the transaction
 | 
				
			||||||
		env.state.StartRecord(tx.Hash(), common.Hash{}, env.tcount)
 | 
							env.state.Prepare(tx.Hash(), common.Hash{}, env.tcount)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		err, logs := env.commitTransaction(tx, bc, coinbase, gp)
 | 
							err, logs := env.commitTransaction(tx, bc, coinbase, gp)
 | 
				
			||||||
		switch err {
 | 
							switch err {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,28 +26,32 @@ import (
 | 
				
			|||||||
var (
 | 
					var (
 | 
				
			||||||
	// MainnetChainConfig is the chain parameters to run a node on the main network.
 | 
						// MainnetChainConfig is the chain parameters to run a node on the main network.
 | 
				
			||||||
	MainnetChainConfig = &ChainConfig{
 | 
						MainnetChainConfig = &ChainConfig{
 | 
				
			||||||
		ChainId:        MainNetChainID,
 | 
							ChainId:         MainNetChainID,
 | 
				
			||||||
		HomesteadBlock: MainNetHomesteadBlock,
 | 
							HomesteadBlock:  MainNetHomesteadBlock,
 | 
				
			||||||
		DAOForkBlock:   MainNetDAOForkBlock,
 | 
							DAOForkBlock:    MainNetDAOForkBlock,
 | 
				
			||||||
		DAOForkSupport: true,
 | 
							DAOForkSupport:  true,
 | 
				
			||||||
		EIP150Block:    MainNetHomesteadGasRepriceBlock,
 | 
							EIP150Block:     MainNetHomesteadGasRepriceBlock,
 | 
				
			||||||
		EIP150Hash:     MainNetHomesteadGasRepriceHash,
 | 
							EIP150Hash:      MainNetHomesteadGasRepriceHash,
 | 
				
			||||||
		EIP155Block:    MainNetSpuriousDragon,
 | 
							EIP155Block:     MainNetSpuriousDragon,
 | 
				
			||||||
		EIP158Block:    MainNetSpuriousDragon,
 | 
							EIP158Block:     MainNetSpuriousDragon,
 | 
				
			||||||
		Ethash:         new(EthashConfig),
 | 
							MetropolisBlock: MainNetMetropolisBlock,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Ethash: new(EthashConfig),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TestnetChainConfig contains the chain parameters to run a node on the Ropsten test network.
 | 
						// TestnetChainConfig contains the chain parameters to run a node on the Ropsten test network.
 | 
				
			||||||
	TestnetChainConfig = &ChainConfig{
 | 
						TestnetChainConfig = &ChainConfig{
 | 
				
			||||||
		ChainId:        big.NewInt(3),
 | 
							ChainId:         big.NewInt(3),
 | 
				
			||||||
		HomesteadBlock: big.NewInt(0),
 | 
							HomesteadBlock:  big.NewInt(0),
 | 
				
			||||||
		DAOForkBlock:   nil,
 | 
							DAOForkBlock:    nil,
 | 
				
			||||||
		DAOForkSupport: true,
 | 
							DAOForkSupport:  true,
 | 
				
			||||||
		EIP150Block:    big.NewInt(0),
 | 
							EIP150Block:     big.NewInt(0),
 | 
				
			||||||
		EIP150Hash:     common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"),
 | 
							EIP150Hash:      common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"),
 | 
				
			||||||
		EIP155Block:    big.NewInt(10),
 | 
							EIP155Block:     big.NewInt(10),
 | 
				
			||||||
		EIP158Block:    big.NewInt(10),
 | 
							EIP158Block:     big.NewInt(10),
 | 
				
			||||||
		Ethash:         new(EthashConfig),
 | 
							MetropolisBlock: TestNetMetropolisBlock,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Ethash: new(EthashConfig),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// RinkebyChainConfig contains the chain parameters to run a node on the Rinkeby test network.
 | 
						// RinkebyChainConfig contains the chain parameters to run a node on the Rinkeby test network.
 | 
				
			||||||
@@ -68,15 +72,15 @@ var (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// AllProtocolChanges contains every protocol change (EIPs)
 | 
						// AllProtocolChanges contains every protocol change (EIPs)
 | 
				
			||||||
	// introduced and accepted by the Ethereum core developers.
 | 
						// introduced and accepted by the Ethereum core developers.
 | 
				
			||||||
	// TestChainConfig is like AllProtocolChanges but has chain ID 1.
 | 
					 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
	// This configuration is intentionally not using keyed fields.
 | 
						// This configuration is intentionally not using keyed fields.
 | 
				
			||||||
	// This configuration must *always* have all forks enabled, which
 | 
						// This configuration must *always* have all forks enabled, which
 | 
				
			||||||
	// means that all fields must be set at all times. This forces
 | 
						// means that all fields must be set at all times. This forces
 | 
				
			||||||
	// anyone adding flags to the config to also have to set these
 | 
						// anyone adding flags to the config to also have to set these
 | 
				
			||||||
	// fields.
 | 
						// fields.
 | 
				
			||||||
	AllProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), new(EthashConfig), nil}
 | 
						AllProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), new(EthashConfig), nil}
 | 
				
			||||||
	TestChainConfig    = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), new(EthashConfig), nil}
 | 
						TestChainConfig    = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil}
 | 
				
			||||||
 | 
						TestRules          = TestChainConfig.Rules(new(big.Int))
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ChainConfig is the core config which determines the blockchain settings.
 | 
					// ChainConfig is the core config which determines the blockchain settings.
 | 
				
			||||||
@@ -95,8 +99,10 @@ type ChainConfig struct {
 | 
				
			|||||||
	EIP150Block *big.Int    `json:"eip150Block,omitempty"` // EIP150 HF block (nil = no fork)
 | 
						EIP150Block *big.Int    `json:"eip150Block,omitempty"` // EIP150 HF block (nil = no fork)
 | 
				
			||||||
	EIP150Hash  common.Hash `json:"eip150Hash,omitempty"`  // EIP150 HF hash (fast sync aid)
 | 
						EIP150Hash  common.Hash `json:"eip150Hash,omitempty"`  // EIP150 HF hash (fast sync aid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	EIP155Block *big.Int `json:"eip155Block,omitempty"` // EIP155 HF block
 | 
						EIP155Block *big.Int `json:"eip155Block"` // EIP155 HF block
 | 
				
			||||||
	EIP158Block *big.Int `json:"eip158Block,omitempty"` // EIP158 HF block
 | 
						EIP158Block *big.Int `json:"eip158Block"` // EIP158 HF block
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MetropolisBlock *big.Int `json:"metropolisBlock"` // Metropolis switch block (nil = no fork, 0 = alraedy on homestead)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Various consensus engines
 | 
						// Various consensus engines
 | 
				
			||||||
	Ethash *EthashConfig `json:"ethash,omitempty"`
 | 
						Ethash *EthashConfig `json:"ethash,omitempty"`
 | 
				
			||||||
@@ -141,6 +147,7 @@ func (c *ChainConfig) String() string {
 | 
				
			|||||||
		c.EIP150Block,
 | 
							c.EIP150Block,
 | 
				
			||||||
		c.EIP155Block,
 | 
							c.EIP155Block,
 | 
				
			||||||
		c.EIP158Block,
 | 
							c.EIP158Block,
 | 
				
			||||||
 | 
							c.MetropolisBlock,
 | 
				
			||||||
		engine,
 | 
							engine,
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -251,6 +258,13 @@ func configNumEqual(x, y *big.Int) bool {
 | 
				
			|||||||
	return x.Cmp(y) == 0
 | 
						return x.Cmp(y) == 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ChainConfig) IsMetropolis(num *big.Int) bool {
 | 
				
			||||||
 | 
						if c.MetropolisBlock == nil || num == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return num.Cmp(c.MetropolisBlock) >= 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ConfigCompatError is raised if the locally-stored blockchain is initialised with a
 | 
					// ConfigCompatError is raised if the locally-stored blockchain is initialised with a
 | 
				
			||||||
// ChainConfig that would alter the past.
 | 
					// ChainConfig that would alter the past.
 | 
				
			||||||
type ConfigCompatError struct {
 | 
					type ConfigCompatError struct {
 | 
				
			||||||
@@ -281,3 +295,22 @@ func newCompatError(what string, storedblock, newblock *big.Int) *ConfigCompatEr
 | 
				
			|||||||
func (err *ConfigCompatError) Error() string {
 | 
					func (err *ConfigCompatError) Error() string {
 | 
				
			||||||
	return fmt.Sprintf("mismatching %s in database (have %d, want %d, rewindto %d)", err.What, err.StoredConfig, err.NewConfig, err.RewindTo)
 | 
						return fmt.Sprintf("mismatching %s in database (have %d, want %d, rewindto %d)", err.What, err.StoredConfig, err.NewConfig, err.RewindTo)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Rules wraps ChainConfig and is merely syntatic sugar or can be used for functions
 | 
				
			||||||
 | 
					// that do not have or require information about the block.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Rules is a one time interface meaning that it shouldn't be used in between transition
 | 
				
			||||||
 | 
					// phases.
 | 
				
			||||||
 | 
					type Rules struct {
 | 
				
			||||||
 | 
						ChainId                                   *big.Int
 | 
				
			||||||
 | 
						IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
 | 
				
			||||||
 | 
						IsMetropolis                              bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ChainConfig) Rules(num *big.Int) Rules {
 | 
				
			||||||
 | 
						chainId := c.ChainId
 | 
				
			||||||
 | 
						if chainId == nil {
 | 
				
			||||||
 | 
							chainId = new(big.Int)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return Rules{ChainId: new(big.Int).Set(chainId), IsHomestead: c.IsHomestead(num), IsEIP150: c.IsEIP150(num), IsEIP155: c.IsEIP155(num), IsEIP158: c.IsEIP158(num), IsMetropolis: c.IsMetropolis(num)}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,7 @@
 | 
				
			|||||||
package params
 | 
					package params
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"math"
 | 
				
			||||||
	"math/big"
 | 
						"math/big"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/common"
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
@@ -38,6 +39,9 @@ var (
 | 
				
			|||||||
	TestNetSpuriousDragon = big.NewInt(10)
 | 
						TestNetSpuriousDragon = big.NewInt(10)
 | 
				
			||||||
	MainNetSpuriousDragon = big.NewInt(2675000)
 | 
						MainNetSpuriousDragon = big.NewInt(2675000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	TestNetChainID = big.NewInt(3) // Testnet default chain ID
 | 
						TestNetMetropolisBlock = big.NewInt(math.MaxInt64)
 | 
				
			||||||
	MainNetChainID = big.NewInt(1) // Mainnet default chain ID
 | 
						MainNetMetropolisBlock = big.NewInt(math.MaxInt64)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						TestNetChainID = big.NewInt(3) // Test net default chain ID
 | 
				
			||||||
 | 
						MainNetChainID = big.NewInt(1) // main net default chain ID
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user